Char* and [MarshalAs(UnmanagedType.LPStr)]

Rhodan

Active member
Joined
Apr 7, 2015
Messages
41
Programming Experience
10+
I have to send byte values to a C dll that is expecting char* which is apparently not allowed. Did some searching and I'm supposed to replace the char* with [MarshalAs(UnmanagedType.LPStr)] string myBytes

That's all fine but I'm trying to figure out how to create a string from a byte array in a way that each character in the string represents the original byte value rather than a three digit string of the decimal value. e.g. If I convert 0xFF to string I end up with a string of "255".

It's probably just that I'm up way too late (had a nap in the afternoon) but I just can't wrap my head around it. Anyway, here's the actual code I'm trying to sort out.

C#:
[DllImport("libpigpiod_if.so", EntryPoint = "i2c_write_device")]     //This is an example of how to call a method / function in a c library from c#
public static extern int i2c_write_device(uint handle, [MarshalAs(UnmanagedType.LPStr)] string buf, uint count);

The original C definition is
int i2c_read_device(unsigned handle, char *buf, unsigned count);

So how would I make an appropriate string out of two bytes like 0x84 and 0xB8?
 
E.g.
var bytes = new[] {0x84, 0xB8};
var chars = Array.ConvertAll(bytes, Convert.ToChar);
var str = new string(chars);

In case you were wondering, this:
var chars = Array.ConvertAll(bytes, Convert.ToChar);


is functionally equivalent to this:
var chars = Array.ConvertAll(bytes, ch => Convert.ToChar(ch));
 
Thanks, i'll try that tomorrow. Been caught up in RL all day and I have an Astronomy outreach event tonight so no chance to try it yet.

Looks like if I'm going to make a wrapper for pigpio then I'll have to make wrappers for all the methods that use char* as well. Maybe have the programmer supply an array of bytes then in the method wrapper do the conversions to strings and then finally to the p/invoke method.
 
On a related note. Is there a simple way to pass a list of bytes to a method? I noticed in the shared library (I think it's just C) you could pass bytes using curly braces and the receiver would automatically treat that as an array of bytes. Like this pseudocode (don't know C sytnax).

C#:
MyCall({0x22,0xF8});

Receiver(byte[] bytes)
{
    DoStuff;
}

I've been unable to find anything similar in C# and it appears that I have to declare and fill a byte array the regular way then use that as an argument to send. Is there a shorthand way like in C (or maybe it was C++, can't tell the difference myself).
 
C# has no way to specify a byte literal but if you declare an array as being type byte then numeric values will be interpreted as bytes, e.g.
MyCall(new byte[] {0x22,0xF8});

Receiver(byte[] bytes)
{
    DoStuff;
}
 
In VB.NET you can denote an array simply by wrapping a comma-delimited list of values in braces. That is a fairly new addition to the language. In C#, you need at least 'new[]' as well, in which case the type will be inferred from the values. In this case, the type would be inferred as 'int' which is the default numbers without a decimal point, so 'byte' must be specified explicitly.

Note that the only time you can use just braces to denote an array is when initialising an explicitly typed variable, e.g.
// Valid
byte[] a = { 0x22, 0xF8 };

// Not valid
var b = { 0x22, 0xF8 };

// Not valid
byte[] c;
c = { 0x22, 0xF8 };
 
Back
Top Bottom