Question

I’m trying to use PInvoke to call a method in a 3rd party DLL which populates an output buffer which I then send to a server using a socket. The method has the following signature:

int APIENTRY loop(HANDLE handle,char *in,unsigned int inLength,
                   char *out,unsigned outBufferSize,
                   unsigned *outLength);

If I call this from a C++ application the out buffer contains signed values which are then sent to a server using the following code:

send(mysocket,outbuffer,outbytes,0);

The problem I have is that socket.Send in C# doesn’t seem to support sbyte[] which I believe is the equivalent to the C++ unmanaged char*? In my C# program I have the following:

[DllImport("vbftam.dll")]
    public static extern int loop(IntPtr handle, IntPtr inputBytes, uint inLength, IntPtr outputBytes, uint outBufferSize, out uint outLength);

I then call the method using the following code:

var outBufferPtr = Marshal.AllocHGlobal(256);
loop(handle, inBufferPtr, inBytes, outBufferPtr, 256, out outbytes)
byte[] myArray = new byte[256];
Marshal.Copy(outBufferPtr,myArray, 0, 256);

If I send myArray to the server the response I get back is not what I was expecting which I assume is due the fact the myArray is unsigned and the server is expecting signed values.

I used the following code to generate a signedArray but socket.Send doesn’t have an overload which takes an sbyte[].

sbyte[] signedArray = new sbyte[myArray.Length];
Buffer.BlockCopy(myArray, 0, signedArray, 0, myArray.Length);

Is this possible in C#? If so how would I go about sending this sbyte[] array using a socket?

Was it helpful?

Solution 2

You can cast your signed array to an unsigned array and then sent it as usual. The underlying data looks the same, it's just how the computer treats it affected by unsigned or signed properties. Here in the table to the right, you can see that both representations have the same bit order. Consider the following signed byte array: [0, -1, 1, 127] you can actually send the unsigned cast of it [0, 255, 1, 127] and get the same result.

OTHER TIPS

You can also use a structure like this:

[StructLayout(LayoutKind.Explicit, Pack = 1)]
private struct Union
{
    [FieldOffset(0)]
    public byte[] ByteArray;
    [FieldOffset(0)]
    public sbyte[] SByteArray;
}

Assign SByteArray to your array and then pass ByteArray to Socket. This way there is no overhead between conversion, however, this is not verifiable and probably not well defined in any spec, so it should only be used in cases where you really need to be very efficient.

Since the Socket class doesn't support sending signed bytes, you'll need to convert your sbyte array into a type that supports the same range, such as int, and send that across to your server. Then, on the server end, you convert that array back to a sbyte[].

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top