我有一些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)
答案 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);
data
和otherData
在C代码中映射到unsigned short *
。
关于返回指向已分配struct
的指针的C代码,您始终可以将C#代码包装在unsafe
区域中,并使用C#中的&
和*
运算符。如果您构建了具有相同布局的有效C#struct
,则可以按预期工作。
答案 3 :(得分:-1)
如果您尝试“转换”为c#,最好使用类而不是结构。
例如,作为一个类,struct REPLY_GETCPL
会更好,因为我看到你也在尝试使用指针。
此外,您可以使用与结构相关联的某些方法,这些结构可以放入类中,并在该类的对象中使用组合功能。
答案 4 :(得分:-1)
如果你想使用指针,你需要一个不安全的blok。看一下这个site。