C# 使用P/Invoke通过套接字发送签名字符*

C# 使用P/Invoke通过套接字发送签名字符*,c#,sockets,pinvoke,C#,Sockets,Pinvoke,我试图使用PInvoke调用第三方DLL中的一个方法,该方法填充输出缓冲区,然后使用套接字将输出缓冲区发送到服务器。该方法具有以下签名: int APIENTRY loop(HANDLE handle,char *in,unsigned int inLength, char *out,unsigned outBufferSize, unsigned *outLength); 如果我从C++应用程序调用这个,缓冲区包含有

我试图使用PInvoke调用第三方DLL中的一个方法,该方法填充输出缓冲区,然后使用套接字将输出缓冲区发送到服务器。该方法具有以下签名:

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

如果我从C++应用程序调用这个,缓冲区包含有符号值,然后使用下面的代码发送给服务器:

send(mysocket,outbuffer,outbytes,0);
var outBufferPtr = Marshal.AllocHGlobal(256);
loop(handle, inBufferPtr, inBytes, outBufferPtr, 256, out outbytes)
byte[] myArray = new byte[256];
Marshal.Copy(outBufferPtr,myArray, 0, 256);
我的问题是,Socket。发送C似乎不支持sBy[],我认为它相当于C++非托管char *。 在我的C#计划中,我有以下几点:

[DllImport("vbftam.dll")]
    public static extern int loop(IntPtr handle, IntPtr inputBytes, uint inLength, IntPtr outputBytes, uint outBufferSize, out uint outLength);
然后,我使用以下代码调用该方法:

send(mysocket,outbuffer,outbytes,0);
var outBufferPtr = Marshal.AllocHGlobal(256);
loop(handle, inBufferPtr, inBytes, outBufferPtr, 256, out outbytes)
byte[] myArray = new byte[256];
Marshal.Copy(outBufferPtr,myArray, 0, 256);
如果我将myArray发送到服务器,我得到的响应不是我所期望的,我假设这是由于myArray未签名,服务器期望有符号的值

我使用以下代码生成signedArray,但socket.Send没有需要sbyte[]的重载

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

这在C#中可能吗?如果是这样,我将如何使用套接字发送此sbyte[]数组?

由于
socket
类不支持发送签名字节,您需要将
sbyte
数组转换为支持相同范围的类型,例如
int
,然后将其发送到服务器。然后,在服务器端,将该数组转换回
sbyte[]

您可以将已签名数组转换为未签名数组,然后像往常一样发送它。底层数据看起来是一样的,只是计算机如何处理受未签名或已签名属性影响的数据。在右边的表格中,您可以看到两种表示具有相同的位顺序。考虑下面的符号字节数组:[ 0,-1, 1, 127 ],您可以实际发送它的未签名的转换(0, 255, 1,127)并得到相同的结果。

也可以使用这样的结构:

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

将SByteArray分配给数组,然后将ByteArray传递给套接字。通过这种方式,转换之间没有开销,但是,这是不可验证的,可能在任何规范中都没有很好的定义,因此它应该只在您确实需要非常高效的情况下使用。

使用sbyte[]没有任何意义,您实际上并不是在解释数据。数组声明不会更改数据。因此,只需使用byte[]并转发它,只有接收数据的应用程序才关心它的外观。非常感谢您的回复,因为您的回答让我走上了正确的轨道。收到服务器的响应后,我再次调用loop方法,通过inBufferPtr传递响应。我需要将响应转换为一个签名数组,它解决了我的问题。