C#调用C/C++的dll须知

来源:转载

1. C#类型与C/C++类型的对应关系

基本数据类型(C# <—> C/C++)
System.Int32,int <—> int, long
System.Int64,int64 <—> long long, __int64
System.Char, char <—> char, byte, unsigned char
System.Int16, short <—> short
System.UInt32, uint <—> unsigned int, unsigned long
System.UInt16, ushort <—> unsigned short, DWORD
System.String, string <—> char[], char , const char
System.IntPtr <—> void *, [Type]*
Sytem.Boolean, bool <—> bool, BOOL


2. C/C++函数参数类型与C#类型对应关系

① 基本的数据类型对应关系与1相同,但是也有一些不一样的地方
② const char * 一般作为输入参数, C#直接使用string类型即可(StringBuilder也可以)
③ char *作为输入参数的时候, C#需要使用ref string类型或者StringBuilder类型
④ 结构体指针做输入参数的时候, C#一般使用ref + 对应的结构体类型


3. C/C++结构体与C#结构体的成员类型对应关系
A. 如果C/C++结构体成员类型是基本数据类型, C#中对应的结构体成员类型使用1中的对应关系即可, 如:

C/C++代码


struct Some
{
int number;
char character;
char name[32];
}

C#代码


struct Some
{
int number;
char charactor;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)]
string name;
}
B. 如果C/C++的结构体成员中包含的成员仍然是结构体(单个,非数组), 则对应的C#结构体只需要同样包含结构体, 如:

C/C++代码


struct A
{
int number;
};
struct B
{
struct A a;
int otherNumber;
};

对应的C#代码


public struct A
{
public int number;
}
public struct B
{
public A a;
public int otherNumber;
}
C. 如果C/C++结构体成员中包含数组(长度固定),则C#结构体中也使用数组对应的类型, 如:

C/C++代码


struct A
{
int number;
};
struct B
{
int numbers[10];
struct A alist[5];
};

对应的C#代码


public struct A
{
int number;
}
public struct B
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10, ArraySubType=UnmanagedType.SysInt)]
public int[] numbers;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=10, ArraySubType=UnmanagedType.Struct)]
public A[] alist;
}
D. 如果C/C++的结构体成员中包含另一个结构体的指针,C#对应的结构体中一律使用IntPtr类型, 如:

C/C++代码


struct A
{
int number;
};
struct B
{
int tag;
struct A *pA;
}

对应的C#代码


public struct A
{
public int number;
}
public struct B
{
public int tag;
public IntPtr pA;
}

然后在使用的时候需要用到Marshal类的StructureToPtr和PtrToStructure方法进行转换
转换方法如下:
(1)结构体转换成IntPtr


A a = new A();
B b = new B();
IntPtr pA= Marshal.AllocHGlobal(Marshal.SizeOf(a));
Marshal.StructureToPtr(a, pA, false);
b.pA = pA;

(2)IntPtr 转换成结构体


B b = new B();
//...省略中间的操作过程
A aInB = (A)Marshal.PtrToStructure(b.pA, typeof(A))
//或者
A aInB = new A();
Marshal.PtrToStructure(b.pA, aInB);
4. 关于类型转换中的数组长度
A. C/C++中,如果是char类型的数组(一般表示最大长度不超过某个数字的字符串),那么在进行参数传递的时候,如果C#中的string字符串字节数超过了C/C++中的最大字节数,则会发生截断, 如C/C++中, char name[3]; 但是在C#中却使用了string name = “Jack”,实际传到C/C++中, name中的内容为“Ja”,多余的部分没有填充进来
B. C/C++中使用的数组为定长数组,在参数传递过程中,如果C#中使用的数组长度比C/C++中数组长度短,则会发生System.ArgumentException异常,提示“未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配“(C#的string到C/C++的char 数组不会,但是C#char[]到C/C++的char数组会有此异常),因此, 我们要定义相同长度的数组才能正常工作(C#数组长度更大的时候,会忽略多余的部分)

分享给朋友:
您可能感兴趣的文章:
随机阅读: