1、平台调用(P/Invoke)实现c#调用c++
1)创建一个c++的dll(vs2019),如下:
这里注意不要把头文件给删了!
c++工程中的代码如下:
extern "C" __declspec(dllexport)
int add1(int a, int b)
{
return a + b;
}
清理解决方案-》重新生成解决方案,生成Main.dll
2)新建一个c#的winform工程,将Main.dll放到winform工程debug目录(程序运行目录)下,新建一个MonitorSample的类,并在类中添加如下代码,并调用
class MonitorSample
{
[DllImport("Main.dll", CallingConvention =CallingConvention.Cdecl)]
internal static extern int add1(int a,int b);
}
调用:
int num = MonitorSample.add1(12, 13);
Console.WriteLine (num);
输出
25
2、利用ref和Out参数实现引用的传递
c++代码
extern "C" __declspec(dllexport)
int add1(int a, int* b)
{
/**b =*b +100;
int c = *b;*/
return a+1;
}
c#代码:
[DllImport("Main.dll", CallingConvention =CallingConvention.Cdecl)]
internal static extern int add1(int a,out int b);
调用:
int ini;
int num = MonitorSample.add1(int.MaxValue , out ini);
3、对于c++中存在的一些没有对应托管类型,使用自定义托管类型实现
c++代码
struct ddd
{
int s;
double b;
};
extern "C" __declspec(dllexport)
int add2(ddd a)
{
int c = a.s;
return c;
}
c#代码
public struct ddd
{
public int s;
public double b;
};
[DllImport("Main.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern int add2(ddd dd);
调用:
ddd dd;
dd.b = 200;
dd.s = 300;
int nums = MonitorSample.add2(dd);
Console.WriteLine(num);
4、异常捕获
可以对于使用extern声明的函数,外加一个包装的函数,函数中加入异常的抛出与处理
[DllImport("Main.dll", CallingConvention =CallingConvention.Cdecl)]
internal static extern int add1(int a,out int b);
internal static int add(int a,int b)
{
int result;
result= add1(a,out b);
if(result <100)
{
}
else
{
throw new Exception("错误");
}
return result;
}
2、指针和地址
1)在c#中直接访问和操纵内存(访问值类型变量的地址)
private void Test()
{
int a = 100;
int value;
unsafe
{
int* aAddress = &a;
value = *aAddress;
}
Console.WriteLine(value);
}
1、使用unsafe提醒编译器支持不安全的代码;
2、将项目-属性-生成-允许不安全的代码选上;
3、不能访问引用类型,例如string,泛型类型的地址;
2)访问数组的地址(在堆上分配内存)
数组的值在内存中存在移动,所以需要将地址固定;
private void Test()
{
byte value;
unsafe
{
byte[] a = new byte[5] { 1,2,3,4,5};
fixed (byte* aAddress = &a[0])
{
value = *aAddress;
}
}
Console.WriteLine(value);
}
3)访问数组的地址(在栈上分配内存)
private void Test()
{
byte value;
unsafe
{
byte* a = stackalloc byte[5] { 1,2,3,4,5};
byte* aAddress = &a[0];
value = *aAddress;
}
Console.WriteLine(value);
}
4)访问被引用变量的成员
struct Postion
{
public double x;
public double y;
}
private void Test()
{
Postion pos;
pos.x = 100;
pos.y = 200;
double value;
double value2;
unsafe
{
Postion* posAdd = &pos;
value = posAdd->x;//一种调用成员的方法
value2 = (*posAdd).y;//另一种调用成员的方法
}
Console.WriteLine(value);
Console.WriteLine(value2);
}