02-03-2015 09:36 PM
Hi,
I have a function in a DLL which returns a C struct. I want to know how can I receive a cluster from a CLFN?
struct info:
struct typedata{
int a;
int b;
const char * c;
int d;
int e;
}data;
function call:
const typedata * hostinfo(int param);
Solved! Go to Solution.
02-04-2015 02:05 AM
There are many posts on this forum about this problem. Answered by Nathan or me. Try to search and you will find them.
Basically it is possible but requires you to play a bit the C compiler. Can be a haunting experience if you don't know C AND how a C compiler works.
You'll have to configure the return value as pointer sized integer and then copy its contents into a compatible LabVIEW structure using either a MoveBlock call (a very good search term for this problem) or the GetValueByPointer node which Nathan often recommends (and is another good search term for this).
02-04-2015 07:21 PM
Hi Rolf,
thanks a lot for your suggestion. I tried getvaluebypointer and it seems to be working fine for most of the cases. It works without any issue if I am trying to dereference integers or strings. However, if I try to dereference a double value, then it messes it up and doesn't output the correct value. Have you ever tried dereferencing a double value using getvaluebypointer? I am using a double precision numeric to dereference a C double datatype.
Another funny thing I found is that moveblock and getvaluebypointer don't return the same value if I try to deference any data type.
eg.
they both output different values and getvaluebypointer returns the correct value.
02-05-2015 01:49 PM - edited 02-05-2015 01:49 PM
Well MoveBlock() works perfectly if configured right. Do you use LabVIEW 64 bit? If not your first parameter is fatally wrong for sure. You should make it a pointer sized integer passed as value, then it will be right for both 32 bit LabVIEW as well as 64 bit LabVIEW. The second parameter must be a 32 bit integer passed as POINTER!
02-05-2015 04:27 PM
As I addressed in my previous post that I am not able to dereference a double value using GetValueByPointer. Here is the example.
I wrote a C code to initialize a double variable with a value 15 and cout its memory address.
I input the same memory address to GetValueByPointer but do not get the correct double value.
Am I doing anything wrong here?
02-05-2015 04:49 PM
You need to be more consistent. First you say GetValueByPointer works, but MoveBlock() doesn't then you suddenly say GetValutByPointer doesn't.
And how do you suppose anyone can tell you what you did wrong from a simple pic? Not seeing any C code you used, nor being able to open the VI and check the configuration, also in the case of the Call Library for the MoveBlock function.
02-05-2015 05:06 PM
LVCoder wrote:
Am I doing anything wrong here?
Yes. You are assuming that all processes share the same address space. If it were that easy for one process to read (and, by extension, trample on) the memory of another process, we'd have even worse software problems than we have now.
02-05-2015 05:22 PM - edited 02-05-2015 05:26 PM
And wait a moment! Are you really expecting an executable that uses some pointer with some value in there, to give you the same result as when you use the pointer value in LabVIEW?????????????????
That's not how every possible modern OS works nowadays. Every modern OS has virtual memory protection. This means that each process has its own virtual memory and no other process can peek into that memory. There is no way around that other than some dirty low level hacks that are to complex to explain to someone or proper interprocess communication such as network, file IO or shared memory access. Each of them requires both sides to explicitedly be programmed to allow that.
And before you ask. Writing a DLL and calling it from both processes won't directly help either unless you use proper interprocess communication. The DLL executablee code is loaded once and mapped as read only section into both processes, but any variables in the DLL will be allocated for each process individually and can't be shared in such a way either.
02-05-2015 09:06 PM
Thanks a lot both of you for letting me know about my dumb assumption that 2 different processes can use the same memory space.
Anyways, I figured out the problem with my code that was reading the double value.
the DLL function returns the address of the struct which has 5 elements.
struct test {
int a;
int b;
int c;
double d;
double e;
}
suppose the address I receive is 10
address of test->a = 10
address of test->b = 14
address of test->c = 18
address of test->d = 26 // I was refering it as address 22. but I forgot that I was on a 64 bit machine and that the OS will allocate the whole memory address for a double and won't utilize the 4 bytes left in the previous memory address.
thanks!
02-06-2015 02:19 AM
@LVCoder wrote:
Thanks a lot both of you for letting me know about my dumb assumption that 2 different processes can use the same memory space.
Anyways, I figured out the problem with my code that was reading the double value.
the DLL function returns the address of the struct which has 5 elements.
struct test {
int a;
int b;
int c;
double d;
double e;
}
suppose the address I receive is 10
address of test->a = 10
address of test->b = 14
address of test->c = 18
address of test->d = 26 // I was refering it as address 22. but I forgot that I was on a 64 bit machine and that the OS will allocate the whole memory address for a double and won't utilize the 4 bytes left in the previous memory address.
thanks!
That has nothing to do with the bitness of your CPU or the OS. It is only dependent on the compiler alignment setting when you compile your DLL. Microsoft Compilers use a default alignment of 8 bytes. That means every variable or element inside a cluster will be aligned to the smaller one of either its own size or the default alignment.
You can change the compiler alignment either with a compiler switch or an explicit #pragma iin your source code where you declare the variables or structure typedefs.