10-31-2019 05:03 PM
I'm trying my first try (in many years) at building C code to be called by LabVIEW. Included in the attached Read1String.zip is my Visual Studio project and everything involved in building the DLL. I have dumbed it down to remove needless dependencies; this simple example depends only on LabVIEW. Here's what's happening. Read1String.c defines a function MakeFakeStrings
which is intended to be called from LabVIEW. I go into the Call Library Function Node and configure it; I browse to find the DLL, with success. I type in the name of the function. But my VI comes up with a broken arrow, reporting that the note can't find or load the DLL. And when I use the little pulldown menu to pick my function, it isn't there; instead I see these:
SetLVRTModule
SetLVRTModuleHook
SetLVRTTLSIndex
SetLVRTTLSIndexHook
What are they? Where did they come from? How might I properly add one to the list? And above all, how do I make this call node happy?
11-01-2019 07:25 AM - edited 11-01-2019 07:47 AM
Well, it would help if you tell the compiler/linker which function you want to export from the DLL.
Adding right after the definition of the Cluster tyepedef a line:
extern "C" void MakeFakeStrings(TD1Hdl *a);
Would both make sure your function is not name mangled when compiled as C++ source and also hint to the compiler that it should be added to the export list.
And using DSNewHandleSize() has the potential to not allocate enough memory because of aligment issues. If you do that for your main handle on 64 bit platforms with 1 dimension (why use two?) your memory block will require 4 more bytes than your calculation will tell you, because of memory allocation.
That said there are many trouble with your code after that change. The first being your 2D indices in the handle, why? Also why don't you update the dimensional size of that before returning. How do you make sure that handle has actually been allocated to be able to take your 4 string handles?
11-06-2019 01:22 PM
Rolf -
Perhaps you forgot that my code file is a .c, not a .cpp file. It knows nothing of extern "C" and gives an error message if I try to use it. Do you have another idea for how to tell the compiler I am exporting this function?
I'm working in two dimensions because the eventual purpose of this exercise is to read a section of an Excel spreadsheet into a two dimensional LabVIEW array of strings. I could do it 1D and then reshape the array in LabVIEW code, but that seems inefficient, doesn't it?
Thanks for the warning on the 64-bit situation, I had forgotten about that.
11-06-2019 01:33 PM
I suppose the following is safe under 32 and 64 bit?
int n = strlen(content);
LStrHandle handle = (LStrHandle)DSNewHandle(sizeof(LStr) + n);
11-07-2019 04:50 PM
Well sorry the extern "C" was misleading. It is only for avoiding name mangling when compiling as C++ code. However the ending of the file is not binding. You can set in a project to compile even C files as C++.
Basically you should have somewhere in a common header something like this:
#if __WIN32__ #define LibAPI(retval) extern __declspec(dllexport) retval #else #define LibAPI(retval) __attribute__((visibility ("default"))) extern retval #endif
Then you can declare your function as:
LibAPI(<return type>) MakeTestStrings(<parameters>);
Only problem with this is that it will not work for functions that should have a void return type. That requires yet another macro. But I simply always add a return value anyways.
11-08-2019 03:56 AM
What you show for a string of course works since the handle element (unsigned char) has 1 byte size and there never will be an alignment issue. It goes potentially wrong as soon as the element type is 8 bytes such as a double or a pointer/handle under 64 bit LabVIEW.