LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Pass a buffer as pointer to a .NET method

Hello,

I didn't find any solution for my problem. I have to translate a C# existing code into Labview. This is an integration of a .NET DLL of Siemens RFID reader RF1070R

 

In C# I have this code:

 

byte[] Data = new byte[512];
fixed (byte* Buf = Data)
{
retval = reader.vhl_read(ReaderHandle, VHLFilenumber, Address, Length, Buf, ref Status);
}

 

I would like to do the same. But I don't see how to pass Buf..? How can I declare a Byte* variable?

 

Thank you for help. Attached zip contain the VI with dependencies.

 

Walker

0 Kudos
Message 1 of 11
(3,979 Views)

Byte* = U8 Array, set it to pass input as pointer.

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 2 of 11
(3,947 Views)

As the C code preallocates the Array, you should use an Initialize Array to create the buffer.

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 3 of 11
(3,943 Views)

Thank you for answering. 

 

I tried but the parameter Byte* Data requests an object as input. See image below, wire is broken. I can't wire an u8 array.

 

Walker34_0-1592468268500.png

 

0 Kudos
Message 4 of 11
(3,880 Views)

Use the To .Net Object.vi method in the .Net palette!

 

To DotNet Object.png

Rolf Kalbermatter
My Blog
Message 5 of 11
(3,858 Views)

I have a similar problem to Walker34, but I don’t understand the answers given. 

 

I am trying to use someone else’s .NET assembly.  One method has the following declaration, as deciphered with CodeReflect 1.0.8:

 

.method public hidebysig instance void QueryBytes(string query, uint8* array, int32& length) cil managed

 

So it wants a pointer to an array of u8’s.  It will populate that array, and I then want to know what’s in the array.

When I initialize an array of U8s and convert it to a .NET object, I get a System.Object, mscorlib, according to the help window.  I can’t wire it directly to the input of the .NET method, because it wants a System.Byte*, mscorlib.  I get a broken arrow instead.  If I try to wire in a “To more specific Class”, with a constant I created from the method’s input terminal, I get an error, “Object cannot be cast to the specified type”, as in the enclosed VI. 

 

Even if I do get these wired together and operational, it’s not clear how I see the information returned by the method.  If I make a branch of the array, will it get manipulated by the .NET call?  That seems unlikely.  Or do I branch the reference and convert it back to a LabVIEW Variant, then Byte Array? 

 

Another, much older thread (https://lavag.org/topic/9844-the-issue-of-calling-dll-passing-arguments-by-pointer/) casually says, “you can always create an intermediate DLL that does translate between whatever the original DLL requires and what works best for the LabVIEW interface”.  We have tried that with the enclosed VBA code, but the pointer we generate again causes wiring conflicts with the target DLL’s input.

Download All
0 Kudos
Message 6 of 11
(3,315 Views)

The function should rather have this prototype

 

void QueryBytes(string query, Byte array[], int32& length);

 

Then LabVIEW would know that it is a byte array and would generate the correct parameter type. The easiest would probably be to create a wrapper in C# (Visual Basic is long obsolete) that simply calls this function but has the correct prototype.

 

uint8* as parameter is ambiguous and in this case in fact an unmanaged datatype and as such only can be handled properly by low level languages like C(++) and requires the programmer to know exactly what he is doing. Basically uint8* could be either a Byte^ parameter or an IntPtr to an memory block containing an array. In this case it is obviously an IntPtr and neither .Net nor LabVIEW can know which one of the two it should be.

 

In the wrapper you would likely have to do something like this:

 

MyQueryBytes(string query, byte[] bytes, int ^length)
{
    fixed(uint8 *unmanagedPointert = packetArray)
    {
        QueryBytes(query, unmanagedPointer, length);
    }
}

 

 

The LabVIEW .Net interface can not do unmanaged code easily.

 

If you really want that you would have to use marshal functions similar to this equivalent code but then with LabVIEW .Net nodes.

 

Int length = 6008;
Byte[] bytes = new Byte[length];
IntPtr unmanagedPointer = Marshal.AllocHGlobal(length);
QueryBytes(query, unmanagedPointer, &length);
Marshal.Copy(unmanagedPointer, bytes, 0, length);
Marshal.FreeHGlobal(unmanagedPointer);

 

Marshal Data.png

Rolf Kalbermatter
My Blog
0 Kudos
Message 7 of 11
(3,299 Views)

You should not forget to close the LabVIEW refnums.

 

Marshal Data.png

Rolf Kalbermatter
My Blog
0 Kudos
Message 8 of 11
(3,283 Views)

Hi,

I'm not sure, but I think that when a .NET method use a pointer as Input, it means that is probably a wrapper for a COM DLL. So can maybe do a wrapper directly into Labview with that COM dll. if you get the header file, it is very fast. That is what I did.

In C# with 'ref' or 'out' argument modifier to modify a variable inside a method. So use of pointers is unusual.

0 Kudos
Message 9 of 11
(3,249 Views)

Native .Net assemblies indeed should not use pointer datatypes. So your guess that it is just an (automatically generated) .Net wrapper for an ActiveX/COM object is most likely right. Accessing the underlaying COM object directly will however only be possible if you can locate it AND it is a full ActiveX server. LabVIEW can not access pure COM interfaces directly as they lack the possibility to uniformly discover the interface definition and require C(++) programming with according.header files to do that.

without having the exact assembly available, it’s difficult to assert for sure. I don’t know how LabVIEW translates this uint8* pointer. If it is a pointer refnum the snippet should work but it could be a number of other things.

 

 

Rolf Kalbermatter
My Blog
0 Kudos
Message 10 of 11
(3,213 Views)