实现c函数和指向c#的参数指针结构? 我对C++的DLL实现到C<有问题

实现c函数和指向c#的参数指针结构? 我对C++的DLL实现到C<有问题,c#,pointers,parameters,struct,dllimport,C#,Pointers,Parameters,Struct,Dllimport,我的头文件代码如下: typedef struct{ uchar Command[4]; ushort Lc; uchar DataIn[512]; ushort Le; }CON_SEND; typedef struct{ ushort LenOut; uchar DataOut[512]; uchar outA; uchar outB; }CON_RESP; SDK_C_DL

我的头文件代码如下:

typedef struct{    
 uchar  Command[4];     
 ushort Lc;    
 uchar  DataIn[512];    
 ushort Le;    
}CON_SEND;



typedef struct{    
 ushort LenOut;     
 uchar  DataOut[512];    
 uchar  outA;    
 uchar  outB;    
}CON_RESP;

SDK_C_DLL_API int   Csdk_Cmd(uchar port, CON_SEND * ConSend,CON_RESP * ConResp);
SDK_C_DLL_API int   Csdk_Open(uchar port);
还有我的C班

现在我使用Csdk_Cmd;工作正常吗?此代码:

if(SDK_C.Csdk_Open(0x00)== 0)
    lblStatus.Text = "Gate 0 is busy";
else
    lblStatus.Text = "You can use Gate 0";
但当我尝试使用此代码时,Csdk_Cmd给出了“NotSupportedException”


<>这是一个猜测,但是你在C++中用内联(固定)数组声明你的结构,所以你也需要告诉C来做。您可以通过以下方式执行此操作:

警告:此代码需要使用unsafe编译,并显示在unsafe块中

或者,您可以研究如何更好地定义结构的封送属性:


(参见下面的DavidHeffernan,下面的答案)

< P>这是一个猜测,但是你在C++中用内嵌(固定)数组声明你的结构,所以你也需要告诉C来做这件事。您可以通过以下方式执行此操作:

警告:此代码需要使用unsafe编译,并显示在unsafe块中

或者,您可以研究如何更好地定义结构的封送属性:


(请参见@DavidHeffernan,下面的答案)

您的结构声明不正确。C代码有内联字节数组,简单地说,它们与
byte[]
的默认编组不匹配。最简单的修复方法是使用
marshallas(UnmanagedType.ByValArray)
。像这样:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CON_SEND
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] Command;
    public ushort Lc;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
    public byte[] DataIn;
    public ushort Le;
}


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CON_RESP
{
    public ushort LenOut;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
    public byte[] DataOut;
    public byte outA;
    public byte outB;
}
函数的返回值也不正确。C
int
映射到C
int
。因此,它们应该是:

[DllImport("SDK_C.dll")]
public static extern int Csdk_Cmd(byte port, ref CON_SEND ConSend, 
    ref CON_RESP ConResp);

[DllImport("SDK_C.dll")]
public static extern int Csdk_Open(byte port);
另一件需要仔细检查的事情是调用约定。上面的C#函数使用默认值
Stdcall
。你确定C代码也可以吗?由于返回值和函数名之间没有指定任何内容,我怀疑函数实际上是
Cdecl
。在这种情况下,您需要:

[DllImport("SDK_C.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Csdk_Cmd(byte port, ref CON_SEND ConSend, 
    ref CON_RESP ConResp);

[DllImport("SDK_C.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Csdk_Open(byte port);

您的结构声明不正确。C代码有内联字节数组,简单地说,它们与
byte[]
的默认编组不匹配。最简单的修复方法是使用
marshallas(UnmanagedType.ByValArray)
。像这样:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CON_SEND
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
    public byte[] Command;
    public ushort Lc;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
    public byte[] DataIn;
    public ushort Le;
}


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct CON_RESP
{
    public ushort LenOut;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
    public byte[] DataOut;
    public byte outA;
    public byte outB;
}
函数的返回值也不正确。C
int
映射到C
int
。因此,它们应该是:

[DllImport("SDK_C.dll")]
public static extern int Csdk_Cmd(byte port, ref CON_SEND ConSend, 
    ref CON_RESP ConResp);

[DllImport("SDK_C.dll")]
public static extern int Csdk_Open(byte port);
另一件需要仔细检查的事情是调用约定。上面的C#函数使用默认值
Stdcall
。你确定C代码也可以吗?由于返回值和函数名之间没有指定任何内容,我怀疑函数实际上是
Cdecl
。在这种情况下,您需要:

[DllImport("SDK_C.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Csdk_Cmd(byte port, ref CON_SEND ConSend, 
    ref CON_RESP ConResp);

[DllImport("SDK_C.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int Csdk_Open(byte port);

我知道发生了什么,但只是为了再次检查你能发布你得到的全部错误吗?我知道发生了什么,但是为了再次检查你能发布你得到的全部错误吗?@DavidHeffernan。不安全的结构可以通过公开内存指针更快地“封送”,但我同意它的可读性/可用性较差。但我无法将数据添加到固定字节数组。CON_SEND cnSend=新CON_SEND();int len=4//只是猜测这个字节[]safe=新字节[len];对于(inti=0;iSendCon.Command=newbyte[]{0xE0,0xA0,0xC4,0x72}@recepakoç您的绩效指标是什么?David的答案(如下)在C#代码中更具可读性/可用性,但它是隐式的双重复制(封送进来,封送出去)。虽然这两种方法都是正确的,但您需要选择最适合您的程序的方法。@MadScienceDreams感谢您的评论和对answer@DavidHeffernan, . 不安全的结构可以通过公开内存指针更快地“封送”,但我同意它的可读性/可用性较差。但我无法将数据添加到固定字节数组。CON_SEND cnSend=新CON_SEND();int len=4//只是猜测这个字节[]safe=新字节[len];对于(inti=0;iSendCon.Command=newbyte[]{0xE0,0xA0,0xC4,0x72}@recepakoç您的绩效指标是什么?David的答案(如下)在C#代码中更具可读性/可用性,但它是隐式的双重复制(封送进来,封送出去)。虽然这两种方法都是正确的,但您需要选择最适合您的程序的方法。@MadScienceDreams感谢您的评论和对答案的更新
CharSet=CharSet.Ansi
CallingConvention=CallingConvention.Cdecl
givven编译时出错。如果我删除它,不会给出错误,但DataOut将填充零。没有数据:(代码对我来说编译得很好。如果你不告诉我编译器的错误是什么,我猜不出来。
CharSet=CharSet.Ansi
CallingConvention=CallingConvention.Cdecl
givven编译时出错。如果我删除它,不会给出错误,但DataOut将填充为零。没有数据:(代码对我来说编译得很好。如果你不告诉我编译器的错误是什么,我猜不出来。