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

时间:2012-10-29 09:21:17

标签: 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      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#

//I think this one is defined right
[DllImport("DoremiSource.dll")]
public static extern void hex_print([MarshalAs(UnmanagedType.LPStr)]string data, UInt32 length);

//(How to convert the function return type?)
[DllImport("DoremiSource.dll")]
public static extern DRMKLVItem *NewDRMKLVItem(UInt32 lenBuff, UInt32 cmdId);  //(4)

//(How do i convert the function parameters here)
[DllImport("DoremiSource.dll", CharSet = CharSet.Ansi)]
public static extern int DRMKLVLengthDecode(const UInt8 *s, ref UInt32 pLen);  //(5)

5 个答案:

答案 0 :(得分:3)

您可以使用复杂类型并在C和C#之间编组它们,您只需要了解结构的编译选项,然后装饰C#类型,如下所示: (来自MSDN

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

答案 1 :(得分:0)

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

C ++ / CLI特别适合处理安全和不安全的代码。您可以在C#和C中执行任何操作。

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

这样你就可以完全控制界面,并有一个很好的调试接入点。

答案 2 :(得分:0)

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

生产代码示例:

[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
public static extern void CCode(ushort[] data, ushort[] otherData, int width, int height);

dataotherData在C代码中映射到unsigned short *

关于返回指向已分配struct的指针的C代码,您始终可以将C#代码包装在unsafe区域中,并使用C#中的&*运算符。如果您构建了具有相同布局的有效C#struct,则可以按预期工作。

答案 3 :(得分:-1)

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

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

答案 4 :(得分:-1)

如果你想使用指针,你需要一个不安全的blok。看一下这个site