how to work with references using ffi? - node.js

I have folowing c++ function compiled with node-gyp.
void InterfaceTestOne(const string & mytest)
{
const string *ptr = &mytest;
printf("The variable X is at 0x%p\n", (void *)ptr);
cout << mytest.length() << endl;
cout << mytest << endl;
}
and nodejs code:
var math = ffi.Library(main, {
"_Z16InterfaceTestOneRKSsi": ["void", [ref.refType(string)]],
});
var output = ref.allocCString('hello alex');
console.log("length", output.length) #12
console.log("address", output.address()) #4353704472
console.log("ref", output.ref()) # <Buffer#0x103804228 18 42 80 03 01 00 00 00>
math._Z16InterfaceTestOneRKSsi(output.ref())
#c++ output
The variable X is at 0x0x103804230
4347093136 <-- mytest size
This is TestOne
hello alex�����s�P��X��0��
����������������������p
p�]���^#��psp���5�����#4������(�����G����� ��qf���6�ՃP���f���6�Ճ���q�X؃ \���u������������3������3������!Ą
p�?�����p �J
����h����������8n���������8v
�d�����s����� ����������(������a......
So instead of string size 12 i got in c++ size 4353704472
ref address in nodejs and c++ also is difference 0x103804228 and 0x0x103804230.
and looks that's why i got in addition to my text a ton of garbage.
Any idea how to fix that?

Related

I'm trying to use I2C with beaglebone but I cannot write more than 1 byte

I'm trying to control DAC5571 with Beaglebone Black. My kernel version is:
Linux beaglebone 4.14.108-ti-r137 #1stretch SMP PREEMPT Tue Aug 25 01:48:39 UTC 2020 armv7l GNU/Linux
I can partially the control the DAC IC. As you can see here, you need to send 3 bytes; Slave Address, CTRL/MSB and LSB. The IC recognizes Slave address bytes and CTRL/MSB. I can read and confirm the output of the output pin. But when I start increasing the voltage value slowly as Vout += 0.05, output increasing as 0.2, 0.4, 0.6, etc...
I've checked with my oscilloscope and I can confirm that the third byte is being transmitted as 0x00 no matter what its the actual value is.
Here is my source code:
int DAC5571::writeI2CDeviceByte(int value)
{
cout << "Starting DAC5571 I2C sensor state write" << endl;
char namebuf[MAX_BUS];
snprintf(namebuf, sizeof(namebuf), "/dev/i2c-%d", I2CBus);
int file;
if ((file = open(namebuf, O_RDWR)) < 0) {
cout << "Failed to open DAC5571 Sensor on " << namebuf << " I2C Bus" << endl;
return(1);
}
if (ioctl(file, I2C_SLAVE, I2CAddress) < 0) {
cout << "I2C_SLAVE address " << I2CAddress << " failed..." << endl;
return(2);
}
int buffer[2];
buffer[0] = value>>8;
buffer[1] = value & 0xFF;
cout << "buffer [0] is " << buffer[0] << endl;
cout << "buffer [1] is " << buffer[1] << endl;
if (write(file, buffer, 2) != 2) {
cout << "Failure to write values to I2C Device address." << endl;
return(3);
}
close(file);
cout << "Finished DAC5571 I2C sensor state write" << endl;
return 0;
}
Here is the console output:
Starting DAC5571 I2C sensor state write
buffer [0] is 3
buffer [1] is 128
Finished DAC5571 I2C sensor state write
I've seen on my research there is a header file called as "i2c-core.h" but I could not include into my projects which has a block write function. Not sure if that would help in my situation.
Can anyone please help me to solve my issue about not being able to transmit LSB part of the data?
Thank you.
int buffer[2];
buffer[0] = value>>8;
buffer[1] = value & 0xFF;
if ( write(file, buffer, 2) != 2) { ... }
The elements of buffer are of type int, which is 4 bytes long. So when you write buffer with a length of 2, you write 2 bytes, which are the first two bytes of the integer buffer[0]. In your example buffer[0] is 3, so since this machine is little-endian, it consists of the bytes 03 00 00 00 and you write out 03 00.
You probably want unsigned char buffer[2]; or maybe uint8_t buffer[2];, so that each element is a byte.

Identify virtual network interface in c

I am trying to find which interface my device is running on with C.
I scanned all interfaces with ioctl, I arranged the result as :
iface 0 ==> lo IP = 127.0.0.1 FLAGS = 00000049 MAC: 00 00 00 00 00 00
iface 1 ==> eth0 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 2 ==> eth0.1 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 3 ==> ra0 iface no IP FLAGS = 00001043 MAC: 40 D6 3C 02 74 10
iface 4 ==> br-lan IP = 192.168.100.1 FLAGS = 00001043 MAC: 40 D6 3C 02 74 11
iface 5 ==> apcli0 IP = 192.168.1.17 FLAGS = 00001043 MAC: 42 D6 3C 02 74 10
iface 6 ==> mon0 iface no IP FLAGS = 00001002 MAC: 40 D6 3C 02 74 10
I used getifaddrs() to get list of interfces, then ioctl (IP using SIOCGIFADDR), (flags using SIOCGIFFLAGS) enum net_device_flags, and (mac using SIOCGIFHWADDR).
From the list, I can identify the loopback, non-working interfaces that do not have IP. I still have two interfaces that are identical FLAGS and have IP (apcli0 & br-lan).
The br-lan is a virtual interface.
Is there away to identify if the interface is virtual (with C)?
Here is my code:
int i;
int fd;
int cnt = 0;
struct ifaddrs *addrs,*tmp;
char ibuf[256];
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
getifaddrs(&addrs);
tmp = addrs;
while (tmp)
{
if ( (tmp->ifa_addr) && (tmp->ifa_addr->sa_family == AF_PACKET)) {
printf("iface %i ==> %s\n", cnt, tmp->ifa_name);
// get ip
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, tmp->ifa_name, IFNAMSIZ);
if (ioctl(fd, SIOCGIFADDR, &ifr) == 0) {
printf("IP = %s\n", (char *)inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
} else {
printf("iface no IP\n");
}
// flags
if (ioctl(fd, SIOCGIFFLAGS, &ifr) == 0) {
printf("FLAGS = %08X\n", ifr.ifr_flags);
} else {
printf("iface no flags\n");
}
// mac addr
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == 0) {
memcpy(ibuf, ifr.ifr_hwaddr.sa_data, 6);
printf("MAC: ");
for (i=0; i<6; i++) {
printf("%02X ", ibuf[i] & 0xFF);
}
printf("\n");
} else {
printf("iface no mac\n");
}
cnt++;
}
tmp = tmp->ifa_next;
}
freeifaddrs(addrs);
Thanks.
I don't believe this is possible with information returned by getifaddrs(), because there are no SIOCGIFFLAGS which indicate that a device is virtual. You can find some of the virtual devices by, for example, checking for the IFF_LOOPBACK flag in iface->ifa_flags (loopback is a virtual interface), but there isn't information in the struct which says specifically whether the device is physical or virtual.
With reasonably recent Linux kernels (not sure starting one, but it has to at least provide a sysfs), I believe this can be determined by examining /sys/class/net -- the directories here will represent the interfaces reported by ifconfig and getifaddrs(), and will either be symlinked to a device in /sys/devices/platform (physical devices) or /sys/devices/virtual (virtual devices). I don't know of a clean way to do this in "regular C" (with nice sane function calls and then checking a flag for physical or virtual), but it seems possible to do it by examining the directory structure in /sys.
edit: looks like pci devices, which are physical devices, can also show up under /sys/devices/pci0000:00 or similar, so not all physical devices are going to be in /sys/devices/physical, so a better check is that /sys/class/net directories aren't symlinked to /sys/devices/virtual directories...
Following c++ snippet is based on #sinback answer.
#include <iostream>
#include <filesystem>
#include <cstring>
#include <vector>
#include <limits.h>
#include <stdlib.h>
namespace fs = std::filesystem;
char buf[PATH_MAX];
int main()
{
std::string path = "/sys/class/net";
for (const auto & entry : fs::directory_iterator(path))
{
auto res = realpath(entry.path().c_str(), buf);
if (res) {
auto abs_path = fs::path(buf);
auto abs_path_splits = std::vector<fs::path>(abs_path.begin(), abs_path.end());
if (abs_path_splits[3].filename() == "virtual") {
std::cout << "VIRTUAL ";
} else {
std::cout << "PHYSICAL ";
}
std::cout << "DEVICE " << entry.path() << " evaluates to " << buf << std::endl;
} else {
std::cerr << " Error (" << errno << "): " << strerror(errno) << std::endl;
return EXIT_FAILURE;
}
}
return 0;
}

example for yaml-cpp 0.5.3 in linux

I am pretty new to yaml-cpp. After did tutorials, that tutorials are fine. But When I try to Parse my own yaml file, it's a litte difficult for me. I am confused with "operator" and "node".
yaml file is shown below.
Device:
DeviceName: "/dev/ttyS2"
Baud: 19200
Parity: "N"
DataBits: 8
StopBits: 1
Control:
Kp: 5000
Ki: 8
FVF: 100
VFF: 1962
Could you anyone give me an example to get data from that yaml file? thanks for your help.
Also i followed this question , I can build it. But When I run it, I got Segmentation fault (core dumped)
Code:
#include <yaml-cpp/yaml.h>
#include <string>
#include <iostream>
using namespace std;
int main()
{
YAML::Node config = YAML::LoadFile("init.yaml");
//read device
std::string DeviceName = config["Device"][0]["DeviceName"].as<std::string>();
int Baud = config["Device"][1]["Baud"].as<int>();
std::string Parity = config["Device"][2]["Parity"].as<std::string>();
int DataBits = config["Device"][3]["DataBits"].as<int>();
int StopBits = config["Device"][4]["StopBits"].as<int>();
//read control
int Kp = config["Control"][0]["Kp"].as<int>();
int Ki = config["Control"][1]["Ki"].as<int>();
int FVF = config["Control"][2]["FVF"].as<int>();
int VFF = config["Control"][3]["VFF"].as<int>();
cout <<"DeviceName" << DeviceName << endl;
cout <<"Baud" << Baud << endl;
cout <<"Parity" << Parity << endl;
cout <<"DataBits" << DataBits << endl;
cout <<"StopBits" << StopBits << endl;
cout <<"Kp" << Kp << endl;
cout <<"Ki" << Ki << endl;
cout <<"FVF" << FVF << endl;
cout <<"VFF" << VFF << endl;
return 0;
}
your code above results in a bad conversion exception because you access the map items in a wrong way.
instead of
std::string DeviceName = config["Device"][0]["DeviceName"].as<std::string>();
just write
std::string DeviceName = config["Device"]["DeviceName"].as<std::string>();
best regards
robert

cross-platform self-modifying code (Intel/AMD only)

I have searched considerably for an answer to this without success.
In a debugger, one may write instructions and then execute them.
This requires special permissions in the executable image.
I seek to perform this function without the debugger.
Please show me an ASM "hello world" program that has self-modifying code
(perhaps replacing a series of 090H with code to uppercase the 'h' in hello)
and the commands necessary to enable its execution.
The next 2 lines are the before and after machine code for the h->H replacement.
90 90 90 90 90 90 90 90 90 90 90 ; 11 NOPs
8a 26 50 00 80 e4 df 88 26 50 00 ; MOV AH,[BX]; AND AH,0DFH; MOV [BX],AH;
I have complete competence and confidence constructing iAPX86 machine code.
My problem is convincing linux, darwin/yosemite, and windows to allow execution.
In the end, I want to be able to construct and modify an executable
on-the-fly for a new language I am writing.
The architecture of the new language has no parallels in modern practice.
I expect much criticism for flying in the face of convention,
but I will proceed with my plans notwithstanding.
Thank you all for taking my question seriously.
This code works! It turned out to be far simpler than I thought;
without special compiler flags, or ELF or MACHO specialization.
In iAPX86 machine code, C3 is near RET without a return value.
I have a few improvements to make, listed after the code,
but this question, as asked, is completely answered to my satisfaction.
working code
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
typedef void (*fptr)();
int main(int argc, char **argv) {
try {
fptr p = (fptr)"\xc3";
p();
cout << "Hello world" << endl;
}
catch (const int e) { cout << "int exception: " << e << endl; }
catch (const char e) { cout << "char exception: " << e << endl; }
catch (const string &e) { cout << "string exception: " << e << endl; }
catch (...) { cout << "default exception" << endl; }
exit(0);
}
TODO
bracket opcode strings with safety code.
prevent certain opcodes from appearing in strings.
catch signals as well as exceptions.

Why is value only changed when referenced as calling argument?

In this code:
#include <iostream>
int num1 = 0;
using namespace std;
void add(int &number);
int main()
{
int num2;
int num3;
add(num1);
cout << "Num1 is: " << num1 << ". Yep, " << num1 << ".";
}
void add(int &number)
{
number++;
}
The passed value "num1" to "add" will change it, but in this code:
#include <iostream>
int num1 = 0;
using namespace std;
void add(int number);
int main()
{
int num2;
int num3;
add(num1);
cout << "Num1 is: " << num1 << ". Yep, " << num1 << ".";
}
void add(int number)
{
number++;
}
It does not change, the value of "num1". Why is that?
In the second case, you increment a COPY of the paramter. In the first case, with the "reference", you modify the variable itself.
Look up "pass by value vs pass by reference. For example:
Pass by reference
Call by value
It should be noted that C (unlike C++) is always "pass by value" ... but the equivalent can be achieved by passing a pointer to a variable.
In the first case number is a reference to num1. That is that number is reference to the same place in memory num1 refers to. Similar to a pointer but without the hassle of dereferencing it.
In the second number is created in the activation record of add, and placed on the stack. When add terminates the number variable is poped off (and the memory of number is deallocated) the stack, and num1 is left unchanged in main's stack and activation record.
If it were an object and not a primitive, this could be seen in the debugger by where the segfault would occur if you were to manually called the destructor just before add returned.

Resources