1. C++ 与 C# 共享同一个int对象:(可推广至一般类型对象)
C#中的函数参数声明与使用传参时增加ref标识符,对应C++的函数参数声明时加上&引用符号;
//C#
[DllImport("MyDll",CallingConvention = CallingConvention.Cdecl)]
private static extern bool Function1(ref int _num);
int in_num=10; //声明输入的int变量
int out_num=0; //声明输出的int变量
Function1(ref in_num); //传入变量 进入C++ dll中处理 并传出
out_num=in_num; //in_num传出时,已经改变
//C++
extern "C" __declspec(dllexport) bool Function1(int &_num)
{
_num=_num++; //将传入的_num改变并且传出
}
2. C++与C#共享一个double数组(可推广至除了字符串类型的一般类型数组)
就像正常传递一个数组一样,但是C#中需要提前声明好空间;
//C#
[DllImport("MyDll",CallingConvention = CallingConvention.Cdecl)]
private static extern bool Function2(double[] _nums);
double[] in_nums = new double[256]; //声明传入的in_num数集,预先分配空间
double[] out_nums = new double[256]; //声明传出的out_nums数集,预先分配空间
Function2(in_nums); //传入处理,并传出;
out_nums =in_nums ; //in_nums传出时已经改变
//C++
extern "C" __declspec(dllexport) bool Function2(double in_nums[])
//或者声明double* _pointsway一个道理,是完全一样的
{
double numone=1.0;
in_nums[0]=numone; //正常的使用即可,但是别超过C#中声明的空间
}
3. C++与C#传递字符串
很奇怪,使用类似于double数组的方法传递C#的string或者char[]都无法修改里面的值,但是C++确实是可以接收到数据,只是如果做出了修改,C#无法收到;
想要传入C++ dll的字符串还可以传回来,C#的函数字符串参数要声明成StringBuilder类型;
/*只传进C++中处理,而不用传出,C#函数声明参数为string型,C++函数声明参数为
char[]型即可*/
//C#
[DllImport("PlayWithC4Plus", CallingConvention = CallingConvention.Cdecl)]
private static extern bool Function3(string _str);
string str = "hello";
Function3(str);
Console.WriteLine(str); //输出依旧是hello,C++中的改变没有传回来
//C++
#define _CRT_SECURE_NO_WARNINGS //使用strcpy要加上这个
#include <iostream>
using namespace std;
extern "C" __declspec(dllexport) bool Function3(char _str[])
//或者声明double* _pointsway一个道理,是完全一样的
{
cout << _str<<endl; //输出hello,证明确实可以传入
char* str = "hello you";
strcpy(_str, str ); //改变_str的值
cout << _str << endl; //输出hello you,C++中的_str确实发生了改变
return true;
}
/*如果想将字符串传进C++,并且C#还可以接收到修改后的值,那就要在C#的函数声明以及参数
传入时使用StringBuilder类型代替string类型*/
//C#
[DllImport("PlayWithC4Plus", CallingConvention = CallingConvention.Cdecl)]
private static extern bool Function4(StringBuilder _str);
string str = "hello";
StringBuilder abuf = new StringBuilder(str);
abuf.Capacity = 100; //设置字符串最大长度
Function4(abuf);
Console.WriteLine(abuf); //区别来了,abuf的值被修改,证明方法可行。
//C++ 与上种只传入不传出的C++代码完全一致
#define _CRT_SECURE_NO_WARNINGS //使用strcpy要加上这个
#include <iostream>
using namespace std;
extern "C" __declspec(dllexport) bool Function3(char _str[])
//或者声明double* _pointsway一个道理,是完全一样的
{
cout << _str<<endl; //输出hello,证明确实可以传入
char* str = "hello you";
strcpy(_str, str ); //改变_str的值
cout << _str << endl; //输出hello you,C++中的_str确实发生了改变
return true;
}
4. C++的dll应该放在什么地方才能被C#程序找到?
应该放在C#工程的exe所在目录,因为从原理上讲,C#会编译成exe,然后运行的时候寻找dll处理外部函数。
5. [DllImport("PlayWithC4Plus", CallingConvention = CallingConvention.Cdecl)]
此语句的后一句是说使用C调用约定(即用__cdecl关键字说明)。如果不加上这句可能会出现以下错误:
函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。