LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

PostLVUserEvent and Embarcadero (C Builder)

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 ?

 

 

0 Kudos
Message 1 of 30
(2,888 Views)

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.

 

 

Rolf Kalbermatter
Averna BV
Message 2 of 30
(2,880 Views)

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

0 Kudos
Message 3 of 30
(2,875 Views)

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.Smiley Very Happy

 

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.

0 Kudos
Message 4 of 30
(2,859 Views)

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.

 

Rolf Kalbermatter
Averna BV
0 Kudos
Message 5 of 30
(2,853 Views)

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.

0 Kudos
Message 6 of 30
(2,825 Views)

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.

Rolf Kalbermatter
Averna BV
0 Kudos
Message 7 of 30
(2,815 Views)

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.

Rolf Kalbermatter
Averna BV
0 Kudos
Message 8 of 30
(2,804 Views)

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

0 Kudos
Message 9 of 30
(2,779 Views)

@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.

 

Rolf Kalbermatter
Averna BV
0 Kudos
Message 10 of 30
(2,775 Views)