从C#调用C代码-遇到了几个问题

从C#调用C代码-遇到了几个问题,c#,c,C#,C,我有一些C代码,我试图从C#使用它们。大部分转换已完成。不过我有几个问题 部分“C”代码如下所示 typedef struct r_GetCPL { UInt8 Storage; UInt8 Key[16]; //(1) UInt8 *Buff; //(2) Array16 *CryptoKeyIDs; //(3) } REPLY_GETCPL; 在“C”中定义的别名 typedef unsigned char

我有一些C代码,我试图从C#使用它们。大部分转换已完成。不过我有几个问题

部分“C”代码如下所示

typedef struct r_GetCPL {

  UInt8 Storage;
  UInt8 Key[16];             //(1) 

  UInt8 *Buff;               //(2)
  Array16 *CryptoKeyIDs;     //(3)

} REPLY_GETCPL;
在“C”中定义的别名

typedef unsigned char      UInt8;
typedef unsigned short     UInt16;
typedef unsigned long      UInt32;
typedef unsigned long long UInt64;

typedef UInt8   Array8[8];
typedef UInt8   Array16[16];
typedef UInt8   Array32[32];
typedef UInt8   Array64[64];
typedef UInt8   Array128[128];
我假设可以用直接结构定义替换typedef。这样好吗? 我定义的等价C#struct是

public struct REPLY_GETCPL 
{
  Byte Storage;
  Byte[16] Key;          //(1) Is this right?

  UInt8 *Buff;           //(2)  What is the equivalent?
  Array16 *CryptoKeyIDs; //(3)  What is the equivalent?
}
此外,还有一些导入方法是我一直坚持的

void hex_print(char* data, UInt32 length);
DRMKLVItem *NewDRMKLVItem(UInt32 lenBuff, UInt32 cmdId);
RESULT DRMKLVLengthDecode(const UInt8 *s, UInt32 *pLen);
C#

如果您试图“转换”为c#,最好使用类而不是结构

例如,作为一个类,您的
struct REPLY\u GETCPL
会更好,因为我看到您也在尝试使用指针。
此外,您可以将某些方法与结构相关联,将其放入类中,并在该类的对象内使用组合功能。

如果要使用指针,则需要一个不安全的blok。看看这个。

从C使用C的一种方法是将C代码包装在C++/CLI对象中

C++/CLI特别适合于处理安全和不安全代码。你可以做你在C和C中能做的任何事情

通过创建托管对象并用(静态)函数填充它来定义接口,以调用非托管C代码。在每个函数中,您都可以执行将参数和结果从托管代码转换为非托管代码所需的封送处理,反之亦然


这样,您就可以完全控制接口,并有一个很好的调试访问点。

您的
UInt8*
参数可以用C#中的数组表示,因为它就是这样。也就是说,对C代码的调用应该使用
UInt8[]
类型

生产代码中的示例:

[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void CCode(ushort[] data, ushort[] otherData, int width, int height);
数据
其他数据
映射到C代码中的
无符号短*


对于返回指向已分配的
结构的指针的C代码,您可以始终将C代码包装在
不安全的
区域中,并在C中使用
&
*
运算符。如果您使用相同的布局构造了一个有效的C#
结构

您可以使用复杂类型并在C和C之间封送它们,您只需知道该结构的编译选项,然后按照以下方式装饰C#类型: (来自)


您似乎不是在转换代码,而是在绑定代码,因为您是从本机库调用函数,而不是重新实现它们。在这种情况下,您可能需要查看C++/CLI以编写绑定。它理解C结构,可以直接定义可从C#使用的对象。您还应该使用和成员偏移量注释结构布局。然而,根据,您可能在成员指针方面运气不佳。因为大多数代码已经使用C#绑定,所以我需要在C#本身中实现这一点。如何解决2、3、4和5个问题。如果您现在有一些C++/CLI方法的链接,那就太好了。有趣的问题……在我自己的经验中,C#讨厌指针。处理托管代码中的指针总是会导致问题。寻找像IntPtr结构这样的东西,它应该会有很大帮助。很抱歉造成混淆。我试图从C#调用一些现有的C代码(实际上并没有转换它)。我如何在这方面达到(2)、(3)、(4)和(5)?这是一个可怕的建议
REPLY\u GETCPL
应该是一个结构。如果使用指针,为什么作为一个类更好?结构也可以有方法。我不明白这为什么会被否决。有人能解释一下我遗漏了什么吗?因为ref不能与C代码一起工作。你需要一个C指针,我知道的唯一方法就是在C#中使用不安全的块。
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void CCode(ushort[] data, ushort[] otherData, int width, int height);
[StructLayout(LayoutKind.Explicit, Size=16, CharSet=CharSet.Ansi)]
public class MySystemTime 
{
   [FieldOffset(0)]public ushort wYear; 
   [FieldOffset(2)]public ushort wMonth;
   [FieldOffset(4)]public ushort wDayOfWeek; 
   [FieldOffset(6)]public ushort wDay; 
   [FieldOffset(8)]public ushort wHour; 
   [FieldOffset(10)]public ushort wMinute; 
   [FieldOffset(12)]public ushort wSecond; 
   [FieldOffset(14)]public ushort wMilliseconds; 
}