LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

call library function node: malloc to recieve a struct

Thanks Rolf,

when I read "write a wrapper DLL that provides that callback function pointer and in there you translate that event into a more LabVIEW user friendly event" it just confused me even more. I understand LabVIEW and occurances and user events; but not DLLs.

What would have made this a lot clearer (to me at least) would be to say that the input to the client's DLL (where a pointer to a user function) is expected will be wired to an user event refnum with type = adapt to type, and Data Format = Handles by Value.

The LabVIEW side of this is very straight forward to me, but keeping the client's DLL happy is where you keep losing me.

even your earlier posting:

http://forums.ni.com/ni/board/message?board.id=170&thread.id=88974&view=by_date_ascending&page=1

didn't help until I saw the uservevent.zip example that you attached (a picture really is worth a thousand words)

thanks again

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Message 41 of 50
(1,974 Views)

No, that may not be right, just reading this article http://zone.ni.com/devzone/cda/tut/p/id/4852 , and maybe the event reference gets fed to the wrapper DLL(?) so then what gets fed to the input of client's DLL?

back to the drawing board

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Message 42 of 50
(1,970 Views)


@lmd2 wrote:

No, that may not be right, just reading this article http://zone.ni.com/devzone/cda/tut/p/id/4852 , and maybe the event reference gets fed to the wrapper DLL(?) so then what gets fed to the input of client's DLL?

back to the drawing board



No, no! The user event refnum is NOT a callback function pointer! It's the refnm that is passed to PostLVUserEvent() as first parameter. So you will write a DLL which provides the actual callback function, and a second function to be called by LabVIEW to install that callback and possibly to revoke it too, dpending on the DLL.

The callback function then calls PostLVUserEvent whenever it is called using the UserEvent refnum that you passed from LabVIEW to the InstallCallback. If your DLL install callback allows passing of a user data item (usually 32 bits) that gets then passed to the callback as extra parameter, you can simply pass the userevent refnum as this user data to the registration function and when your callback function is invoked retrieve that user data and cast it back into the refnum and then invoke PostLVUserEvent().

When the registration does not allow for passing a user data item things get a little more difficult since you will have to store the refnum somewhere (like in a global variable) and reference it from the callback function.

I'm afraid I can't really explain it more easily than this in conjunction with the example you also found. You are dealing with callbacks, function pointers and such and that are definitely advanced C programming topics. If you can't wrap your head around this you are in good company but it will make it virtually impossible to get this working yourself.

Rolf Kalbermatter


Message Edited by rolfk on 07-10-2008 07:25 PM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 43 of 50
(1,960 Views)

Let's step back a second. This entire effort is to convert a device driver written in C to LabVIEW. LabVIEW programmers aren't going to be writing callback functions in C anyway, The intent is when one of the interrupts enabled in the mask occurrs, the user can do 'something'. Ideally if one of the interrupts occurrs a LabVIEW programmer will want to run some G code (not C code).

What would be ideal is some way to coerce or cast an event reference so that the clients function would accept it, and then simply run some LabVIEW code (say in an event structure) and skip the C function pointer completely?

Basically I want to use the clients function which triggers on an interrupt to run something on my block diagram, not really a C function - otherwise how will this be usefull to C-challenged LabVIEW coders

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Message 44 of 50
(1,955 Views)


@lmd2 wrote:

Let's step back a second. This entire effort is to convert a device driver written in C to LabVIEW. LabVIEW programmers aren't going to be writing callback functions in C anyway, The intent is when one of the interrupts enabled in the mask occurrs, the user can do 'something'. Ideally if one of the interrupts occurrs a LabVIEW programmer will want to run some G code (not C code).

What would be ideal is some way to coerce or cast an event reference so that the clients function would accept it, and then simply run some LabVIEW code (say in an event structure) and skip the C function pointer completely?

Basically I want to use the clients function which triggers on an interrupt to run something on my block diagram, not really a C function - otherwise how will this be usefull to C-challenged LabVIEW coders



Well, it would be ideal but basically impossible. LabVIEW simply has not enough information to be able to do such coercion automatically and a configuration dialog that would allow you to tell LabVIEW how to do this right would be an entire magnitued more complicated than the Call Library Node configurationalready is (which would basically mean that only people can understand it that know enough that they would go the C wrapper route anyhow).

And your end user is not going to deal with that at all even when you decide to give him the VI library as a development Toolkit. But someone has to do the translation between LabVIEW and C. For simple functions calls this can be done in the Call Library Configuration dialog. For more advanced things you may need to resolve to some tricks in the LabVIEW diagram with data copying such as you have encountered with the cluster/structure already. While you can do this still in LabVIEW it soon gets so complicated that writing a wrapper DLL that translates between the C interface and a more friendly LabVIEW function interface to be called by the Call Library Node is actually getting easier than trying to do yourself all those things that a C compiler normally takes care of automatically.

And when callback functions get involved a wrapper DLL is really the only sane solution. Anything else is going to be a nightmare in terms of maintainability of your code And soneone has to write this wrapper DLL. Once it is written all the other users of your VI library won;t even know they are dealing with a C interface. That is after all the whole idea about writing an interface VI library.

Basically interfacing to a DLL in LabVIEW can be classified as follows:

1) API has simple functions that take only scalar parameters either by reference or value, simple C pointer arrays and strings allocated by the caller. -> easy to interface although it is some work even when using the Import Library Wozard since you have to verify it anyhow afterwards as the Wizard can always create faulty code.

2) API with more complicated parameters like structures or callee allocated buffers. -> Still possible to do entirely in LabVIEW but you need to do some serious work on the diagram and a wrapper DLL is soon the better choice if you have more than a few functions that need such translation.

3) Adavanced features such as callbacks or functon pointers in general. -> Wrapper DLL is basically unavoidable if you want to stay sane and keep it maintainable.There have been solutions promoted involving LabVIEW created DLLs or .Net remoting but they all have serious drawbacks that make it almost unbearable to support such a solution in the long run.

Rolf Kalbermatter


Message Edited by rolfk on 07-10-2008 08:22 PM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 45 of 50
(1,953 Views)

ok so I have to learn this

found an example "Posting Events to a LabVIEW Event Structure From a Dll" at http://zone.ni.com/devzone/cda/epd/p/id/1480

I'll look this over and try to gain some insight. One thing that still makes no sense to me, I have to wire something into the input of the CLFN for the original function, in my earlier problem (pointer to a pointer to a struct) my dll allocates a block of memory, returns the address which then gets passed to the client's dll. In this case what if anything gets passed to the clients dll?

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Message 46 of 50
(1,935 Views)
ok, spoke to NI - if I understand this now, the CLFN will call my wrapper DLL, which will access the clients function internally, LabVIEW will not call the clients function through a CLFN ever. Glad someone finally said that it clears up a number of misconceptions.So nothing gets 'wired'. But even internally I need to supply some input to the clients function (textually). Since we want to do the real action on the block diagram would this be a call to a dummy function that simply returns a status? Can that dummy function be part of the same DLL or should it be external?

Starting to make sense, let me think on this a little more
Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Message 47 of 50
(1,929 Views)


@lmd2 wrote:
ok, spoke to NI - if I understand this now, the CLFN will call my wrapper DLL, which will access the clients function internally, LabVIEW will not call the clients function through a CLFN ever. Glad someone finally said that it clears up a number of misconceptions.So nothing gets 'wired'. But even internally I need to supply some input to the clients function (textually). Since we want to do the real action on the block diagram would this be a call to a dummy function that simply returns a status? Can that dummy function be part of the same DLL or should it be external?

Starting to make sense, let me think on this a little more

Well I assumed that this would be made clear by the userevent.zip file that you found in my post earlier on. This is basically more similar to what you try to do than the NI example you found in your previous post.

So lets look at the file from my userevent.zip. It's not very useful in terms of what it does since you can do the same with a notifier in LabVIEW much easier but quite educating in how it does it.

RegisterUserEvent(LVUserEventRef *value, int32 delay) is the exported function that gets called by the LabVIEW CLFN to register (and unregister) the callback. This function calls eventually timeSetEvent() a Windows API that installs a callback function to be called periodically. The callback function is OneShotTimer() implemented in that file too.

Basically timeSetEvent() would be where you would principially call the register callback function from the API you want to control and OneShotTimer() would be the callback function that API would expect, of course adapted to the prototype of the required callback function.

I hope this clears up some of the confusion you may still have.

Rolf Kalbermatter


Message Edited by rolfk on 07-11-2008 07:47 AM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 48 of 50
(1,923 Views)

Hi Rolf

conceptually I think I am finally getting this (nice when the light finally comes on)

I am working on the mechanics, bit of a learning curve but I am finding examples, I'll get it.

A question on architecture, or organization - I am going to need two functions to handle the wrapping of "the pointer to a function"  (in one of the client's functions) and one or two to handle the earlier issue of "pointer to a pointer" and maybe others as I continue working on this driver project - Is it considered good practice to have a single DLL containing all of these pairs of functions?

 

 

thanx for all your help; and your patience - 

 lmd2

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Message 49 of 50
(1,902 Views)


@lmd2 wrote:

Hi Rolf

conceptually I think I am finally getting this (nice when the light finally comes on)

I am working on the mechanics, bit of a learning curve but I am finding examples, I'll get it.

A question on architecture, or organization - I am going to need two functions to handle the wrapping of "the pointer to a function"  (in one of the client's functions) and one or two to handle the earlier issue of "pointer to a pointer" and maybe others as I continue working on this driver project - Is it considered good practice to have a single DLL containing all of these pairs of functions?

thanx for all your help; and your patience - 

 lmd2



Definitly! It will make maintianing that project much more easy. It would be a different story when you would support two rather different drivers. While you could still put everything in one file it may be more sensible to keep a differetn DLL for each driver type, eventhough if that might mean copying some functionality, but it is all a question of good sense, your own preferences and some "Fingerspitzengefühl".

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 50 of 50
(1,898 Views)