平台调用P-INVOKE完全掌握(完结篇),自定义Mashaler

这是P-INVOKE系列的最后一篇,也是万剑归宗的一篇,基本上只要函数签名对了,用他可以传递任何参数,函数的输入输出参数和返回值你也可以随心所欲地修改。

把这个放在最后也是最完美的结局吧!!

 

C++:测试代码如下:

 

复制代码
  
  
1 struct Test
2 {
3 int test;
4 };
5
6   // static Test _test;
7  
8 Test GetTest(Test * lpTest)
9 {
10 lpTest -> test = 200 ;
11 return * lpTest;
12 }
复制代码

 

 

C#:在P-INVOKE中,我把C++指针参数Marshal成C#类的输入参数,把C++返回值为结构体的Marshal成字符串。注意下面的P-INVOKE声明。

UnmanagedType.CustomMarshaler表明使用自定义的marshaler.

 

复制代码
  
  
1 [StructLayout(LayoutKind.Sequential)]
2 public class Test
3 {
4 public int test;
5 }
6
7
8 public class PInvokeTest
9 {
10 [DllImport( " TestDll " )]
11 [ return :MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef = typeof (TestMashaler),MarshalCookie = " output " )]
12 public static extern string GetTest([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (TestMashaler), MarshalCookie = " input " )] ref Test test);
13 // 把返回值Marshal成字符串,自定义Marshal 参数。
14  
15 public void Run()
16 {
17 Test test = new Test();
18 test.test = 100 ;
19
20 string temp = GetTest( ref test);
21 Console.WriteLine(test.test + " , " + temp);
22 }
23
24 }
复制代码

 

 

 

自定义marshaler要实现ICustomMarshaler接口,并且提供一个类函数public static ICustomMarshaler GetInstance(string cookie),

微软方法的名字很好懂,我也不再一一解释了。关键地方代码中也有注释。

 

 

复制代码
  
  
1 public class TestMashaler : ICustomMarshaler
2 {
3 private static object _refObject = null ;
4 private string _cookie = string .Empty;
5
6 public TestMashaler( string cookie)
7 {
8 _cookie = cookie; // 保存是输入参数使用的Mashaler,还是输出参数使用的Mashaler.
9   }
10
11 public void CleanUpManagedData( object ManagedObj)
12 {
13 }
14
15 public void CleanUpNativeData(IntPtr pNativeData)
16 { // 清理非托管内存,防止内存泄露
17   Marshal.FreeHGlobal(pNativeData);
18 }
19
20 public int GetNativeDataSize()
21 {
22 return Marshal.SizeOf( typeof (Test));
23 }
24
25 public IntPtr MarshalManagedToNative( object ManagedObj)
26 {
27 if (ManagedObj is Test)
28 { // 保存ref引用。
29   if (_cookie == " input " ) _refObject = ManagedObj;
30 IntPtr p = Marshal.AllocHGlobal(Marshal.SizeOf( typeof (Test)));
31 Marshal.StructureToPtr(ManagedObj, p, false );
32 return p; // Marshal成指针。
33   }
34 else throw new NullReferenceException();
35 }
36
37 public object MarshalNativeToManaged(IntPtr pNativeData)
38 {
39 if (pNativeData != IntPtr.Zero)
40 {
41 int temp = pNativeData.ToInt32();
42 if (_cookie == " input " )
43 { // 输出参数返回
44   (_refObject as Test).test = temp;
45 return _refObject;
46 }
47 else if (_cookie == " output " )
48 { // 返回值返回。
49   return pNativeData.ToString();
50 }
51 return null ;
52 }
53 else throw new NullReferenceException();
54 }
55
56 public static ICustomMarshaler GetInstance( string cookie)
57 {
58 return new TestMashaler(cookie);
59 }
60 }
复制代码

 

 

最后还是建议大家使用微软提供的,自己实现的虽然很灵活很BT很邪门,但是还是很容易出错。上面的代码也仅供娱乐消遣了!!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值