LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Callback from LabView DLL

Hi,

I need help implementing a callback from LV DLL, but first I think a brief
description of what I'm doing is necessary.

We have an application that we want do extend with LabView functions, so
we are building a LV DLL. The app needs a certain type of export table in the
DLL and has its own way of doing callback, so I have made a wrapper DLL
with Visual C++ to implement this. Now we can make calls from the app
to LV DLL via the wrapper, but making callbacks seems a lot harder to
implement.

The architecture looks something like this
____                      ________                         _______
|App  |  ---call- -->   |Wrapper |     ---call----->   | LV DLL |
|____|<-callback-   |        DLL |    <-callback - |_______|
                            |________|

App loads the wrapper DLL which loads the LV DLL.

I have two different approaches for the callback

1. Create a CIN in the LV DLL and pass a function pointer from wrapper DLL
to LV DLL an use the CIN for callback with the function pointer.

2. Since only one instance of a DLL is in the memory at one time, when the
wrapper loads the LV DLL also the LV DLL loads the wrapper DLL. By this
I could use the functions of the wrapper directly from the LV DLL. Usually
in DLL the code is shared and the data is private to each loader of the DLL,
but with special kind of compiling/linking I can make a shared section in the
DLL that can be used as inter process communication channel. The
Microsoft documentation says that it is not safe to have pointers or function
pointers in the shared section, since that might cause problems, so I'm
thinking whether this is a good idea or not.

So, I would like to have comments from more experienced LV user about this.
If someone has made something similar, maybe with either one of the two
methods I described or with some other method that I haven't thought of.

Thanks.
0 Kudos
Message 1 of 8
(3,801 Views)

Hi,

I have a liittle bit of trouble to understand, what you really want. 🙂

The Microsoft books of Jeffrey Richter clearly explain the callback mechanisms and the queues that are needed to implement them.

I would avoid to work with an unkown special compiling and linking scheme, but rather use well known semaphores or similar.

There is also the thread local storage concept, which can help you to implement static storage with threads within a dll. But TLS also uses up real resources, so you shouldn't implement TLS blindly for all dlls.

0 Kudos
Message 2 of 8
(3,781 Views)

Hi kaem,

      I'm no DLL expert but have a couple of questions/ideas anyway! Smiley Wink



2. Since only one instance of a DLL is in the memory at one time...


Is this true?  LabVIEW can load multiple instances of DLL with the Call Library Function configured for a "reentrant" call - is C (C++) limited to not-allow multiple instances?

Would it be useful/simpler to pass an event from the app to the LabVIEW DLL (or through it to a CIN) and have the LabVIEW DLL invoke the event instead of actually calling a function?  (In the app., the function could be run when the Event fires.)

 I didn't really understand the part of your post re: inter-process communications...

Cheers!

"Inside every large program is a small program struggling to get out." (attributed to Tony Hoare)
0 Kudos
Message 3 of 8
(3,777 Views)
Thank you Martin and tbd for your replies.

I will try to explain the situation better.

We have an application where we want to make a call to LabView DLL.
This is not possible directly, so we have another DLL that wraps the LV DLL.
The wrapper exports its function to the app and calls the LV DLL's functions.

In some cases, a LV DLL needs to do a long measurement and the app can not
wait for the measurement to be ready. So we create a thread in LV that will do
the measurement and the app is now free to do other things. When the LV thread
is ready with the measurement it needs to inform the app about that. For this
callback would be needed. The callback from the wrapper to app is clear, all we
need is a callback from LV DLL to wrapper.

Hopefully this time it makes sense Smiley Very Happy

Martin what is the exact book that you mentioned? Does it explain a way to make a
callback in a situation like the one I described?

And Martin, does your idea of semaphores still apply? How?



There is also the thread local storage concept, which can help you to implement static storage with threads within a dll. But TLS also uses up real resources, so you shouldn't implement TLS blindly for all dlls.

This part I don't understand at all.


I'm not a DLL expert either, but as far as I know, a DLL is loaded in to memory once.
The DLL has a reference counter that indicates how many processes have loaded it.
When the counter hits 0, the DLL is ready to be removed from the memory. Inside
the DLL the code section is shared among processes, but the data section is private
to each process. At least with VC++ it's possible to declare a data section in the DLL that
is shared with the processes, but like I said the documentation does not recommend that
pointers or function pointers are shared this way.

I don't know how LV loads DLLs. Maybe you have to configure the call to be reentrant
to have private data for all processes. Otherwise its shared. If someone knows about
this, please explain.



@tbd wrote:

Would it be useful/simpler to pass an event from the app to the LabVIEW DLL (or through it to a CIN) and have the LabVIEW DLL invoke the event instead of actually calling a function?  (In the app., the function could be run when the Event fires.)


This is something I also don't understand, can you clarify.

tbd, what did you not understand in the part of inter-process communications?

I have also thought of using named pipes or UDP messages to make the communication,
but I believe that this will increase the latency, since we are not operating directly in memory.
Also, doing this would require to me program a message waiting mechanism in the wrapper,
and I think it would make things even more complicated.



0 Kudos
Message 4 of 8
(3,768 Views)
It's possible to use a callback mechanism, but it's a hassle.

You need to make a dll in LabVIEW, and use LoadLibrary and GetProcAddress to
get a pointer to it.

It's much easier to link your custom dll with labview.lib (in cintools), and
call SendUserEvent from your dll. Instead of a callback pointer, you pass an
event reference to your dll. Use a normal event structure to wait for the
user event.

Regards,

Wiebe.


0 Kudos
Message 5 of 8
(3,745 Views)
Thank you Wiebe for your reply.

I think you got me wrong. I need to make a callback from
LabView to another program. So I can't use LabView Events,
because I can't handle them with C++.

I have already made a DLL with LV and I'm loading it from C++ with
LoadLibrary() and get the funtion pointers with GetProcAddress().
There's no problem wih this.

Do you know is it possible to pass a function pointer from C++ to
LabView and  use CIN to make callback with that function pointer?

The callchain is working as it should(from app to LabView DLL via the
wrapper DLL). What I need now is a callback from LabView to app.
The callback from the wrapper DLL to app is working, so actually
I only need a callback from LV DLL to the wrapper DLL.
0 Kudos
Message 6 of 8
(3,730 Views)
If you can export the callback function, you can call it like any other dll
function. As far as the function knows, it's called just like a normal
callback is called.

If you can't export the function (somebody else's code), you need some other
way to get the callback's pointer. Then making a wrapper is easy. Don't make
a CIN, but make a dll. CIN's are considered obsolete, although not
officially.

I made an assembler dll once that does this. It uses one function to store
the address, and another to be called with the same parameters as the actual
function. See:

http://forums.ni.com/ni/board/message?board.id=170&message.id=39381&view=by_date_ascending&page=2

Regards,

Wiebe.


0 Kudos
Message 7 of 8
(3,712 Views)
Thank you Wiebe for your reply.

I have been thinking about this issue in a too complex way. If I'm correct
I don't need any shared section or such. Just exporting the callback
functions from the wrapper to the LV DLL should do the trick.

Like I wrap the calls to LV DLL inside the wrapper, I'll just wrap the
callbacks from LV DLL to the app also.

I'll give this a try, and report back here whether it worked or not.

Thanks to everyone who contributed to this thread.
0 Kudos
Message 8 of 8
(3,670 Views)