LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

call library function node: malloc to recieve a struct

so okay, the hardware driver checks the availavle buffer:
 _try
    {
        ProbeForWrite(pCh10Pkt, sizeof(MTI_CH10_DATA_PKT) + (pdc -> MtiDataPoolBufferSize[Channel] -
            MTI_POOL_OVERHEAD_SIZE), sizeof(CHAR));
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        return MTI_ERR_INVALID_BUFFER;
    }
and in C the allocation is done thus:
 
S32BIT    dwPktPoolSize   = 0x20000;
 
/*allocate memory for MTI packages*/
pPkt = (MTI_CH10_Data_PKT*) malloc(dwPktPoolSize);
 
so even if LabVIEW is allocating space, it doesn't have a handle, does it? If the driver is checking for memory with a handle of (MTI_CH10_DATA_PKT) it will fail (?) does this sound reasonable? is there some way to assign a handle to a buffer in LabVIEW?
Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
0 Kudos
Message 31 of 50
(1,427 Views)


@lmd2 wrote:
so okay, the hardware driver checks the availavle buffer:
 _try
    {
        ProbeForWrite(pCh10Pkt, sizeof(MTI_CH10_DATA_PKT) + (pdc -> MtiDataPoolBufferSize[Channel] -
            MTI_POOL_OVERHEAD_SIZE), sizeof(CHAR));
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        return MTI_ERR_INVALID_BUFFER;
    }
and in C the allocation is done thus:
 
S32BIT    dwPktPoolSize   = 0x20000;
 
/*allocate memory for MTI packages*/
pPkt = (MTI_CH10_Data_PKT*) malloc(dwPktPoolSize);
 
so even if LabVIEW is allocating space, it doesn't have a handle, does it? If the driver is checking for memory with a handle of (MTI_CH10_DATA_PKT) it will fail (?) does this sound reasonable? is there some way to assign a handle to a buffer in LabVIEW?


I don't think that is the problem. The only thing I can think of is that the driver is NOT tryng to access the buffer during the call where you pass in the array buffer but only later.

That would have to fail since a LabVIEW array buffer is only guaranteed to exist for the duration of the Call Library Call to which it is passed. remember that LabVIEW data is strictly dynamically allocated and the memory belonging to a wire is more or less immediately deallocated as soon as a wire stops to exist in the diagram dataflow. After that if the wire gets not wired further LabVIEW deallocates that array buffer more or less immediately or if you wire it further but to some function that does modify its size somehow it will reallocate it, which most times will cause the buffer to be moved in memory rendering the previously passed in memory pointer invalid.

So what you can do for a quick check for this theory is wiring the array as in your last solution where you create it outside the loop but wire it through the data function (with an array output too. Then connect that wire to the loop boundary to cause LabVIEW to hold onto that buffer. Make sure the wire stays existing in terms of dataflow until after you issue the stop command and the state of the driver has finished the stop command.

If this solves the problem you want to do something else then that is more robust and logical. That is allocating that buffer as a C size buffer calling into some system API for memory allocation. This pointer is then treated as uInt32 and used whereever necessary and after it is not needed anymore you deallocated it with the according system API.

Rolf Kalbermatter


Message Edited by rolfk on 07-08-2008 05:50 PM
Rolf Kalbermatter
My Blog
0 Kudos
Message 32 of 50
(1,418 Views)

Hi Rolf, nice to have you back

but if I understood you correctly, it didn't help.

I wired the array through to an indicator, to the edge of the while loop, and then out to the loop that closes the execution - same error - INVALID BUFFER

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
Download All
0 Kudos
Message 33 of 50
(1,404 Views)

Just spoke with the client again, he feels that the issue is that we aren't dealing with a pointer to a struct, but a pointer to a pointer to a struct (he says that the next release of the DLL will simplify this, but for now this is what we have).

malloc returns [a pointer to a memory location] to (PMTI__CH10_DATA_PKT*);

pPkt is a pointer to that pointer

but I don't see how that invalidates the buffer?

This has implications for another sample program which I haven't coded yet. It uses this same function "aceGetCh10DataPkt" and then writes a binary file of the raw data begining at location pPkt - the problem here is that in LabVIEW the function (using the CLFN) doesn't return a pointer to the memory location, but rather the cast STRUCT

Resolving both these issues seems related, but I am not sure how



Message Edited by lmd2 on 07-08-2008 01:07 PM
Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
0 Kudos
Message 34 of 50
(1,400 Views)


@lmd2 wrote:

Just spoke with the client again, he feels that the issue is that we aren't dealing with a pointer to a struct, but a pointer to a pointer to a struct (he says that the next release of the DLL will simplify this, but for now this is what we have).

malloc returns [a pointer to a memory location] to (PMTI__CH10_DATA_PKT*);

pPkt is a pointer to that pointer

but I don't see how that invalidates the buffer?

This has implications for another sample program which I haven't coded yet. It uses this same function "aceGetCh10DataPkt" and then writes a binary file of the raw data begining at location pPkt - the problem here is that in LabVIEW the function (using the CLFN) doesn't return a pointer to the memory location, but rather the cast STRUCT

Resolving both these issues seems related, but I am not sure how



Message Edited by lmd2 on 07-08-2008 01:07 PM

Well that explains everything. When you configure the Call Library Node to pass in an array pointer it passes in the pointer not a pointer to that pointer. And there is no way to directly tell the Call Library Node to pass a pointer to a pointer. The native LabVIEW handle would be a pointer to a pointer but you can't use that since LabVIEW will on return interprete the first 4 bytes in that memory as the number of array elements that follow. So you will get not the correct data back.

The only way that can be dealt with is using a call to an external function to allocate that memory, treat it as an uInt32 as far as LabVIEW is concerned passing it by reference to the DLL and then using a MoveBlock call or similar to copy the data out of that buffer when you need it. Of course don't forget to dispose of that buffer at the end either.

Just thougth of something else. You could still use a normal LabVIEW buffer and create a small external function that takes the array configured as C pointer and copies it into an uInt32 that then gets passed as uInt32 by reference to the DLL. Saves you the MoveBlock later on which I would consider a performance gain.

Rolf Kalbermatter


Message Edited by rolfk on 07-08-2008 10:57 PM
Rolf Kalbermatter
My Blog
Message 35 of 50
(1,386 Views)

Thanx Rolf,

I had thought from my initial post the syntax made it obvious that this was a pointer to a pointer (though the implication was lost on me, and mostly still is)

So now I have a POINTER to a POINTER to a STRUCT, which itself contains a POINTER - (the final array defined only by its first element)

Guess I have a big learning curve ahead of me - I have never written a DLL,  not even sure where to begin (I haven't had a C compiler in years other than Labwindows CVI). And once I learn how to write a DLL I have to figure out what it isa I need it to do - but I have a direction and can stop wasting time doing wrong things 😉

Thanx for your help and patience - I may come back to this thread in a week or two

 

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

Hi Rolf

may I change the subject for a moment and ask you another question?

I have another function with 4 inputs, DevNum, Enable, IRQ Mask, and a pointer to a user defined function.

 

The user sets the IRQ mask, and if a defined interrupt occurrs, the user function gets called; the prototype looks like:

S16BIT _DEC aceSetIrqConditions(S16BIT DevNum, U16BIT bEnable, U32BIT dwIrqMask,

                void(_DEC *funcExternallsr)(S16BIT DevNum, U32BIT dwIrqStatus));

 

How do I configure a function's input to accept a pointer to another function?

thanx

Lawrence M. David Jr.
Certified LabVIEW Architect
cell: 516.819.9711
http://www.aleconsultants.com
larry@aleconsultants.com
0 Kudos
Message 37 of 50
(1,360 Views)
Rolf,

So you would then recommend allocating the memory for the Array in the wrapper DLL.  Passing the pointer to that memory location back to LabVIEW as a uInt32, and getting the data from that memory location with the MoveBlock?
Regards,

Jared Boothe
Staff Hardware Engineer
National Instruments
0 Kudos
Message 38 of 50
(1,348 Views)


@Jared_B wrote:
Rolf,

So you would then recommend allocating the memory for the Array in the wrapper DLL.  Passing the pointer to that memory location back to LabVIEW as a uInt32, and getting the data from that memory location with the MoveBlock?


That's the more simple solution. You do not strictly need a DLL wrapper since you can also call DSNewPtr in the same way as MoveBlock directly from LabVIEW (and of course don't forget to call DSDisposePtr at the end).

The more sleazy way is to construct a pointer to a pointer with an extra DSNewPtr that allocates a 4 byte memory block, then copies the contents of the first buffer pointer into it and then passes the reference to that 4 byte buffer as pointer to the real pointer to the function in question. Needs some pointer brain exercise to get it right but avoids the performance overhead of having to copy the data repeatedly out of the buffer after each call.

Rolf Kalbermatter
Rolf Kalbermatter
My Blog
0 Kudos
Message 39 of 50
(1,343 Views)


@lmd2 wrote:

Hi Rolf

may I change the subject for a moment and ask you another question?

I have another function with 4 inputs, DevNum, Enable, IRQ Mask, and a pointer to a user defined function.

 

The user sets the IRQ mask, and if a defined interrupt occurrs, the user function gets called; the prototype looks like:

S16BIT _DEC aceSetIrqConditions(S16BIT DevNum, U16BIT bEnable, U32BIT dwIrqMask,

                void(_DEC *funcExternallsr)(S16BIT DevNum, U32BIT dwIrqStatus));

 

How do I configure a function's input to accept a pointer to another function?

thanx



I've written elsewhere here already several times about this. And the answer is you basically don't and can't!

You have to bite the bullet and write a wrapper DLL that provides that callback function pointer and in there you translate that event into a more LabVIEW user friendly event. If you do not have any data to send back to LabVIEW with the event you can translate it in an occurrence.

Otherwise you need to translate it into a LabVIEW user event using the LabVIEW exported function PostLVUserEvent(). There are samples here on the NI site if you look for that name in the search.

Rolf Kalbermatter


Message Edited by rolfk on 07-09-2008 11:44 PM
Rolf Kalbermatter
My Blog
0 Kudos
Message 40 of 50
(1,342 Views)