简体   繁体   English

实现C函数和参数指针结构到C#?

[英]implement c function and parameter pointer struct to c#?

I Have a problem about implementint of C++ DLL to C# 我对将C ++ DLL的Implementint转换为C#有问题

My Header File code is this : 我的头文件代码是这样的:

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);

and my C# class 和我的C#类

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CON_SEND
{
    public byte[] Command;
    public System.UInt16 Lc;
    public byte[] DataIn;
    public System.UInt16 Le;
}


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CON_RESP
{
    public System.UInt16 LenOut;
    public byte[] DataOut;
    public byte outA;
    public byte outB;
}


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

[DllImport("SDK_C.dll")]
public static extern System.Int16 Csdk_Open(System.Byte port);

now i use Csdk_Cmd; 现在我使用Csdk_Cmd; is working no problem this code : 此代码正常工作:

if(SDK_C.Csdk_Open(0x00)== 0)
    lblStatus.Text = "Gate 0 is busy";
else
    lblStatus.Text = "You can use Gate 0";

but when i try to use this code Csdk_Cmd given "NotSupportedException" 但是当我尝试使用此代码Csdk_Cmd给定“ NotSupportedException”

CON_SEND SendCon = new CON_SEND(); 
 SendCon.Command = new byte[] { 0xE0, 0xA0, 0xC4, 0x72 };
 SendCon.DataIn = new byte[]{0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xA0};
 SendCon.Lc = 0x0007;
 SendCon.Le = 0x0000;

CON_RESP RespCon = new CON_RESP();
 RespCon.DataOut = new byte[512];

SDK_C.Csdk_Cmd(0, ref SendCon, ref RespCon); // THIS LINE

Your struct declarations are not correct. 您的结构声明不正确。 The C code has inline byte arrays and simply put, they do not match the default marshalling for byte[] . C代码具有内联字节数组,简而言之,它们与byte[]的默认编组不匹配。 The easiest way to fix it is to use MarshalAs(UnmanagedType.ByValArray) . 解决此问题的最简单方法是使用MarshalAs(UnmanagedType.ByValArray) Like this: 像这样:

[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;
}

Your functions also have incorrect return value. 您的函数还具有不正确的返回值。 AC int maps to C# int . AC int映射到C# int So they declarations should be: 因此,它们的声明应为:

[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);

The other thing to double check is the calling convention. 再次检查的另一件事是调用约定。 The C# function above use the default of Stdcall . 上面的C#函数使用默认的Stdcall Are you sure that the C code also does? 您确定C代码也可以吗? Since there is nothing specified between the return value and the function name, I suspect that the functions are actually Cdecl . 由于在返回值和函数名称之间未指定任何内容,因此我怀疑这些函数实际上是Cdecl In which case you need: 在这种情况下,您需要:

[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);

This is more of a guess really, but you are declaring your structs with inline (fixed) arrays in C++, so you'll need to tell c# to to do that too. 确实,这更多的是猜测,但是您使用C ++中的内联(固定)数组声明结构,因此您也需要告诉c#这样做。 You can do this with Fixed Size Buffers : 您可以使用固定大小的缓冲区来做到这一点:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct CON_SEND
{
   public fixed byte Command[4];
   public System.UInt16 Lc;
   public fixed byte DataIn[512];
   public System.UInt16 Le;
}

Warning: this code needs to be compiled with unsafe and appear in unsafe block. 警告:此代码需要使用不安全的代码进行编译,并出现在不安全的代码块中。

Alternatively, you could look into better defining the marshaling attributes for your struct: 另外,您可以考虑为结构更好地定义封送处理属性:

http://www.codeproject.com/Articles/66244/Marshaling-with-C-Chapter-2-Marshaling-Simple-Type http://www.codeproject.com/Articles/66244/Marshaling-with-C-Chapter-2-Marshaling-Simple-Type

(See @DavidHeffernan, answer below) (请参阅@DavidHeffernan,在下面回答)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM