c# 平台调用 传递参数
最近做项目用到了dll,网上介绍了很多,但是真要自己实现起来确实也费了不少功夫,这里有自己基础不扎实的原因,也有客观原因,比如平台调用中,好多细节问题如果注意不到,就会得到错误的答案。下面是些我写的一些小测试程序:
Code
1//str为输入参数,outstr为输出参数
2char* strtest(char* str, int a, unsigned char* outstr);
3
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
7调用函数为:
8 private void button1_Click(object sender, EventArgs e)
9 {
10 //ss();
11 //test2 x = new test2();
12 //x.n1 = 4;
13 //x.n2 = 8;
14 //test2fun(x);
15
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
22 string s = "c:\\data.txt";
23 int a = 0;
24 string ss = "";
25
26 byte[] sb = new byte[256];
27 for (int i = 0; i < 256; i++)
28 {
29 sb[i] = (byte)(256-i);
30 }
31 strtest(s, out a, sb);
32 foreach (int i in sb)
33 {
34 ss = ss + sb[i].ToString() + " ";
35 }
36
37 /**/////StringBuilder sb = new StringBuilder(256);
38 MessageBox.Show(ss);
39 }
40
41应该注意的问题:
421. c#编码方式是unicode,而c里面是Ansi。在传入字符串时,要指定CharSet为Ansi格式,否则会出错。
432. 传入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
45
1//str为输入参数,outstr为输出参数
2char* strtest(char* str, int a, unsigned char* outstr);
3
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
7调用函数为:
8 private void button1_Click(object sender, EventArgs e)
9 {
10 //ss();
11 //test2 x = new test2();
12 //x.n1 = 4;
13 //x.n2 = 8;
14 //test2fun(x);
15
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
22 string s = "c:\\data.txt";
23 int a = 0;
24 string ss = "";
25
26 byte[] sb = new byte[256];
27 for (int i = 0; i < 256; i++)
28 {
29 sb[i] = (byte)(256-i);
30 }
31 strtest(s, out a, sb);
32 foreach (int i in sb)
33 {
34 ss = ss + sb[i].ToString() + " ";
35 }
36
37 /**/////StringBuilder sb = new StringBuilder(256);
38 MessageBox.Show(ss);
39 }
40
41应该注意的问题:
421. c#编码方式是unicode,而c里面是Ansi。在传入字符串时,要指定CharSet为Ansi格式,否则会出错。
432. 传入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
45