01-14-2023 04:23 PM
Hello I hope someone can help me, I have been trying to get this to work for days but no success yet.
What I want to do
I got a dll with a wrapper, this dll and wrapper can be used for a special datalogger. The wrapper contains multiple functions, I have got some of them working using a CLFN, for instance I can read a jumper setting from the datalogger in LabView. So far everything is fine.
Of course I am not that interested in the jumper setting, I would rather use the datalogger to log data.
I need to run one function to start logging. When there is enough data in the databuffer of the driver dll it will call a callback function I need to write in Labview, here is the function which starts the logging as described in the header file:
Int LOGEXPORT __sdcall LOG_StartLogging{const char ** logFilename, ptLogCallbackfunction ptFunction, ptObject ptObject}
logFilename needs to be a NULL pointer, from my understanding I do not need to do anything with it. Only provide it. If I do not do anything with it some data is saved at a default location.
ptLogCallbackfunction, as far as I know I need to provide a pointer to the callback function
ptObject ptObject, this must be a void pointer
The header also provided how the callback function could look like in C:
Void __stdcall callbackLog(ptObject object, const int ArraySize, const StructLogdata *const logDataArray)
{
// copy data from logDataArray for use in your code
}
StructLogdata is a struct with different datatypes.
What I did try
I did a search on internet there are some examples about callback functions, most of them point to NET and active X. They use a reg Event Callback. I did read the helpfile at the end of the helpfile there is the text:
“Use the Event structure or the Register For Events function to register and handle non-.NET or non-ActiveX events dynamically” I am having a hard time to find a proper example. I did find this site with some information:
https://knowledge.ni.com/KnowledgeArticleDetails?id=kA00Z000000P8XJSA0&l=nl-NL
and this one about the refnum:
https://forums.ni.com/t5/LabVIEW/Passing-Event-Refnum-to-Call-Library-Function/td-p/4107748
So I did make a user event, I wired a static Vi ref containing a callback vi to the input of this user event. I did wire the user event to a Reg event and wired the event registration refnum to the start logging dll call library function node function pointer input and also to an event structure. I did place a counter in the event structure. But nothing happens besides for an exception which makes Labview crash.
The parameters I did use in the call library function are:
logFilename: type numeric, datatype: Signed Pointer-sized int Pass: pointer to value
ptLogCallbackfunction: type: adapt to type, Data format handles by value (tried all options)
ptObject: same as logFilename
I did try a lot of different things. Writing them in this post will result in chaos and I don’t want that. I hope someone can help me with a simple example how to make this work, or point me into the correct direction.
Thank you all for the help!
01-16-2023 02:52 AM
For some reason there is no example shipping with LabVIEW, but here is one on the forum: https://forums.ni.com/t5/LabWindows-CVI/using-PostLVUserEvent-function-from-Labview-dll/td-p/2510908
You will have to write another wrapper or edit the existing one that calls the LabVIEW function PostLVUserEvent(). This function takes an LVUserEventRef as its first argument, which gets into your dll as a User Event Refnum. The event registration refnum stays in LabVIEW. The static VI ref sounds like you are mixing .NET callbacks into this, but that's not relevant here.
01-17-2023 01:20 AM
I posted an example here of creating a VI, building it into a DLL where it has the needed signature and then loading the VI as a function from that DLL and passing it as a callback to another DLL.
I haven't had any more experience with this beyond that experiment and I'm sure there are a bunch of possible complications (RTE versions, data types, memory allocations, etc.), but this might help you if you do want to do everything in LV.
01-17-2023 02:42 AM - edited 01-17-2023 02:43 AM
@tst wrote:
I posted an example here of creating a VI, building it into a DLL where it has the needed signature and then loading the VI as a function from that DLL and passing it as a callback to another DLL.
I haven't had any more experience with this beyond that experiment and I'm sure there are a bunch of possible complications (RTE versions, data types, memory allocations, etc.), but this might help you if you do want to do everything in LV.
That's basically the problem I have found with this approach. Nice to show that it can be done, but beyond that there is very little use in it. It's cumbersome, brittle, hard to maintain and very likely to break in the future from all kinds of things, like little new LabVIEW features that suddenly get in the way of this unintended use of LabVIEW DLLs, or even just slightly changed security behaviour in Windows.
You are basically trying to build a 6 story building on a few wooden beams as foundation. Nice as an experiment to show that it can be done, but nobody in his sane mind will go and enter it, lets not talk about living in it.
01-22-2023 05:55 AM
thanx, cordm
this is exactly what I was looking for and you are right, I did mix up the NET callback as I had this as one of the first examples. I made an example and this seems to be working. The C compiler seems to be working and I can get data from Labview to the C dll and transport the data back to Labview.
Now I need to:
I give it a try!
p.s. I took a while to react as my post was seen as spam by NI and he reaction from Ni was delivered to the spam box in my mail, gues the spam detection bots took it a little to personal 🙂