最近做项目用到了dll,网上介绍了很多,但是真要自己实现起来确实也费了不少功夫,这里有自己基础不扎实的原因,也有客观原因,比如平台调用中,好多细节问题如果注意不到,就会得到错误的答案。下面是些我写的一些小测试程序:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
//str为输入参数,outstr为输出参数
2
char* strtest(char* str, int a, unsigned char* outstr);
3![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
[DllImport("FaceLib.dll", EntryPoint = "strtest", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
5
public static extern string strtest(string str,out int a,[In,Out] byte [] outstr);
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
调用函数为:
8
private void button1_Click(object sender, EventArgs e)
9![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
10
//ss();
11
//test2 x = new test2();
12
//x.n1 = 4;
13
//x.n2 = 8;
14
//test2fun(x);
15![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
//FaceDetectModel fdmodel = new FaceDetectModel();
17
//Bitmap bmp = new Bitmap("c:\\image.bmp");
18
//Convert_to_IntImage_ref(ref fdmodel, bmp);
19
//loadFaceDetectModel(fdmodel, "C:\\data.txt");
20
//showFaceDetectModel(fdmodel, "c:\\data1.txt");
21![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
string s = "c:\\data.txt";
23
int a = 0;
24
string ss = "";
25![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
byte[] sb = new byte[256];
27
for (int i = 0; i < 256; i++)
28![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
sb[i] = (byte)(256-i);
30
}
31
strtest(s, out a, sb);
32
foreach (int i in sb)
33![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
34
ss = ss + sb[i].ToString() + " ";
35
}
36
37![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**/////StringBuilder sb = new StringBuilder(256);
38
MessageBox.Show(ss);
39
}
40![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
41
应该注意的问题:
42
1. c#编码方式是unicode,而c里面是Ansi。在传入字符串时,要指定CharSet为Ansi格式,否则会出错。
43
2. 传入char* 用string即可,这方面资料很多,传出用StringBuilder,原因可以参见csdn上的封送字符串,和回调函数部分的介绍。这里要说的是,用StringBuilder来传出参数时,要保证函数执行完保存在非托管函数参数中的值不被释放,比如在原函数char* strtest(char* str, int a, unsigned char* outstr);中如果我把以字符串传入str,然后保存到char* outstr中,要用memcpy()或strcpy()来拷贝,而不能直接outstr=str,这在原函数中执行是没问题的,但是执行完毕后,不能返回到c#的托管函数。其中原因就是outstr只是一个str的copy,或者说outstr和str指向了同一块内存,在非托管函数执行完毕后,outstr就销毁了,自然也不能返回值。
44![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
45![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)