02-05-2013 10:17 AM
Hello,
I have read and understood exemples of using PostLVUserEvent function in dll to fire user events in LV.
http://forums.ni.com/t5/LabVIEW/LabView-user-event-from-external-dll-source/m-p/726883#M332674
The problem is that i have to use RAD studio (Embardero , son of Borland C++ Builder ) to build the dll, and with it, it ends with a linker error:
[ILINK32 Erreur] Error: 'H:\......\LABVIEW.LIB' contient un enregistrement OMF non valide, type 0x21 (COFF possible)
Well, i have tried to use "coff2omf" Rad Studio utility to convert ../Labview2012/cintools/labview.lib but it didn't work.
An other try was to make a third part dll with a single FireEvent function compiled with Visual studio that i should call from my "RAD" dll.
From my test "rad" program, it works well, but of course i have no LVUserEventRef* to provide.
From Labview main vi, the "Rad" dll is loaded but is unable to load the other dll !!???
As anybody ever tried to do that, and find a solution?
Or anyone knows if a version of "PostLVUserEvent" compatible with Borland/Embarcadero exist ?
02-05-2013 11:09 AM
labview.lib is in the Microsoft COFF format, so can't be used directly by any Borland C derived system who expects OMF formated libraries. If the Borland utility can't convert labview.lib it most likely has not been updated to convert the most recent MS C compiler library format. So an option might be to try to convert an older labview.lib library but not earlier than LabVIEW 7.1 since that is when PostLVUserEvent() was introduced.
But there is a simpler way too!
The LabVIEW.lib import library is really a convinience not a total requirement. You can also use LoadLibrary() and GetProcAddress() to load the Library from the LabVIEW kernel. A typical approach would be something along the lines of:
static char aPostLVUserEvent = "PostLVUserEvent";
/* Try to get the handle to the LabVIEW executable module */
HANDLE lib = GetModuleHandle(NULL);
PROCPTR proc = GetProcAddress(aPostLVUserEvent);
if (proc == NULL)
{
/* a built LabVIEW executable does not export any functions, try the runtime library instead */
lib = LoadLibrary("lvrt.dll");
if (lib == NULL)
FAILURE;
proc = GetProcAddress(aPostLVUserEvent);
}
Now you can use lib to get funciton pointers to other LabVIEW manager functions such as the memory manager functions, and call the LabVIEW function through the proc pointer variable without having to use labview.lib at all.
02-05-2013 12:42 PM
Thanks for the quick answer.
You explain clearly what i was guessing.
I think i need a few tries to use the code, but it allready looks like a good idea.
i shall tell you if successfull.
Regards
LC
02-06-2013 10:08 AM
While searching docs about the code you send, i found the LoadLibraryEx() function.
I tried it in my previous code and it untied the last problems.
So now, everythings works and i can fully interract between LV and a Borland code.
The architecture is:
main vi (or executable) in LabView
A Borland form compiled as a dll as a slave.
An other dll used only to Fire events towards LV compiled in VisualC.( i used Code Blocks with VC compiler).
Now about the code you send, do you now where to find parameters of dll "lvrt.dll" functions.
02-06-2013 02:28 PM - edited 02-06-2013 02:32 PM
gosaure wrote:
Now about the code you send, do you now where to find parameters of dll "lvrt.dll" functions.
Yes! Check out the online manual that gets installed with your LabVIEW. Or refer to the manual on the NI website here.
But I'm not understanding why you create that wrapper DLL in CodeBlox at all. If you use the code in my first post to locate the module handle that exports all the LabVIEW manager functions, you do not need to create the intermediate DLL at all and can directly reference the LabVIEW function.
02-11-2013 12:03 PM
Hello
Well, i finally made it the way you suggested, but it does not work ??
I get the module handle, and the proc adress OK, it looks like passing the LV event ref OK, too.
But when i fire the event from the "borland" form, nothing happens in LV, and the PostLVUserEvent function returns 1.
It looks like the event ref is not valid,( or function adress ?), seen from Borland side....?????
And there is a LabView crash at the moment i close the vi (everytime i had it running, even if it stops quite correctly).
As i have my alternative 2 DLLs way to make it work, it is not really important, but i anyway like to understand.
So if you have time to find the reason of the misfunctionnement, thanks to tell me.
Regards
Laurent.
02-11-2013 03:47 PM - edited 02-11-2013 03:48 PM
It would help saving the VI into a previous LabVIEW version as I don't currently have any system with a ready 2012 version readily available.
02-11-2013 04:58 PM - edited 02-11-2013 05:09 PM
One thing that I noticed is that you define the LV function as
typedef int(*F0)(LVUserEventRef* ,void* );
yet NI documents this function here to be:
MgErr PostLVUserEvent(LVUserEventRef ref, void *data);
That would explain the error code 1 which is a "manager argument error" as the refnum argument is of course not recognized as a valid user refnum. Also you should not store the reference to the user event refnum but the user event refnum itself. The reference may get invalid.
The function to be called by LabVIEW through the Call Library Node needs to declare the refnum by reference though, because that is the only way the CLN allows to pass parameters configured to pass native datatypes.
Another remark: I don't know anything about the event handling in Borland C TForms but I definitely would assign the event refnum to the variable before calling Show() on the form.
02-12-2013 05:49 AM
Hello,
_MgErr Post.....
I shall try it as soon as possible.( Lot of things to do this morning). It could be a good clue
_ Also you should not store the reference to the user event refnum but the user event refnum itself.
_ but I definitely would assign the event refnum to the variable before calling Show() on the form.
reponse:
In my "2dll" exemple, i pass the LVUserEventRef the same way i do with the" 1dll" : Handles by value
And i deal with the reference in the Borland code the same way and at the same time too.
LVUserEventRef* type.
joined LabView test code in LV2011.
Laurent
02-12-2013 06:13 AM
@gosaure wrote:
Hello,
_MgErr Post.....
I shall try it as soon as possible.( Lot of things to do this morning). It could be a good clue
In my "2dll" exemple, i pass the LVUserEventRef the same way i do with the" 1dll" : Handles by value
And i deal with the reference in the Borland code the same way and at the same time too.
LVUserEventRef* type.
Then it is only working by chance. The reference (pointer) is only valid for the duration of the function call and the memory it is stored (the stack) will be reused for other things. If you want to use an object elsewhere you need to store the value of the object not a reference to it, or make sure the reference stays valid, but you can't do that for a refernce on the stack as the stack is allocated by each function as needed and automatically given up at the end of the function.