博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P/Invoke Interop 实例
阅读量:7115 次
发布时间:2019-06-28

本文共 5093 字,大约阅读时间需要 16 分钟。

新建一个项目,名为PInvoke:

 

 

建好项目后,添加一个cpp源文件,由于只是一个Demo,我们使用默认的名称Source.cpp:

 

Source.cpp代码如下:

#include 
#include
#include
#include
typedef struct MyType{ int i; char *s; double d; struct MyType *p;} MyType;int TestInt(int a, int b){ return a + b;}void TestIntPtr(int *i){ *i = *i * -1;}char* TestCharPtr(char *a, char *b){ return strcat(a, b);}void TestStructPtr(MyType *p){ p->i++; p->d++;}void TestPtrPtr(int **a, int length){ *a = (int*)malloc(sizeof(int) * length); memset(*a, 0, sizeof(int) * length);}void TestArray(int *a, int length){ for (int i = 0; i < length; i++) { a[i]++; }}void TestCallback(void (*pf) ( )){ pf();}int TestCharWidth(char *s){ return strlen(s);}
添加一个新文件Source.def,用于导出Dll中的函数:

 

内容如下,其中LIBRARY "PInvoke"中的"PInvoke"是项目的名称:

LIBRARY "PInvoke"

    EXPORTS
        TestInt
        TestIntPtr
        TestCharPtr
        TestStructPtr
        TestPtrPtr
        TestArray
        TestCallback
        TestCharWidth

C的工程已经竣工了,下面来在解决方案中新加一个C#项目:

建好后,将ConsoleApplication1项目设置为启动项目,修改Program.cs代码如下:

using System;using System.Collections.Generic;using System.Linq;using System.Runtime.InteropServices;using System.Text;using System.Threading.Tasks;namespace ConsoleApplication1{    class Program    {        [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]        public struct MyType        {            /// int            public int i;            /// char*            [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPStr)]            public string s;            /// double            public double d;            /// myType*            public IntPtr p;        }        public delegate void Callback();        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern int TestInt(int a, int b);        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern void TestIntPtr(ref int i);        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern IntPtr TestCharPtr(System.IntPtr a, System.IntPtr b);        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern IntPtr TestStructPtr(ref MyType myType);        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern void TestArray(int[] a, int length);        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern void TestCallback(Callback callback);        [DllImport("PInvoke.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]        public static extern int TestCharWidth(IntPtr s);        static void CallbackFunction()         {             Console.WriteLine("callback invoked");         }        static void Main(string[] args)        {            // TestInt            Console.WriteLine(TestInt(1, 2));            // TestIntPtr            int i = 1;            TestIntPtr(ref i);            Console.WriteLine(i);            // TestCharPtr            IntPtr helloPtr = Marshal.StringToHGlobalAnsi("hello");            IntPtr worldPtr = Marshal.StringToHGlobalAnsi("world");            IntPtr helloWorldPtr = TestCharPtr(helloPtr, worldPtr);            string helloWorld = Marshal.PtrToStringAnsi(helloWorldPtr);            Console.WriteLine(helloWorld);            Marshal.FreeHGlobal(helloPtr);            Marshal.FreeHGlobal(worldPtr);            // Marshal.FreeHGlobal(helloWorldPtr);  // 因为helloWorldPtr和helloPtr指向的是同一地址,所以再次释放会报错            // TestCharWidth            string a = "a的";            IntPtr aPtr = Marshal.StringToHGlobalAnsi(a); // Ansi            int len = TestCharWidth(aPtr);            Console.WriteLine(len);            a = Marshal.PtrToStringAnsi(aPtr);            Marshal.FreeHGlobal(aPtr);            aPtr = Marshal.StringToHGlobalUni(a); // Unicode            len = TestCharWidth(aPtr); // 值是1,strlen没有正确处理unicode,所以不要使用strlen测量unicode字符串的长度            Console.WriteLine(len);            a = Marshal.PtrToStringUni(aPtr);            Marshal.FreeHGlobal(aPtr);                        // TestStructPtr            MyType myType = new MyType { i = 0, d = 1.1, s = "a的", p = IntPtr.Zero };            TestStructPtr(ref myType);            // TestArray            int[] array = new int[] { 1, 2, 3 };            TestArray(array, array.Length);            // TestCallback            TestCallback(CallbackFunction);            Console.Read();        }    }}

 

为了调试方便,我们在编译好C的dll后,自动把dll拷贝到C#项目的可执行文件目录下。在PInvoke项目上右键,属性,然后如下图:

 

按F5调试一下你的代码吧。

 

PInvoke Interop Assistant

PInvoke Interop Assistant是一个免费的把C/C++代码转成C#/VB.net的工具,非常好用。以下是使用截图:

在左边写native code,右边会自动转换成C#。所以如果有Native的类型不知转成C#该怎么写,它可以直接告诉你。

 

sample代码下载地址:

PInvoke Interop Assistant下载地址:

转载于:https://www.cnblogs.com/dc10101/archive/2012/07/02/2573209.html

你可能感兴趣的文章
React 解决fetch跨域请求时session失效
查看>>
翻译_只需20行代码创造JavaScript模板引擎(二)
查看>>
Blockchain和Tangle哪一个是未来?
查看>>
apicloud拉起小程序并传递参数
查看>>
虚拟机Centos6.8安装MYSQL5.7,本地Navicat连接
查看>>
简单聊聊DOM
查看>>
【JavaScript】JavaScript Array 对象(数组)
查看>>
github 上有趣又实用的前端项目(持续更新,欢迎补充)
查看>>
opencv python 直方图均衡化
查看>>
HotFrameLearning 热门框架学习(前言)
查看>>
git团队开发流程
查看>>
【Under-the-hood-ReactJS-Part6】React源码解读
查看>>
深入理解css之vertical-align
查看>>
Laravel事件
查看>>
matlab绘制peano(皮亚诺)曲线和koch(科赫曲线,雪花曲线)分形曲线
查看>>
使用pipenv代替virtualenv管理python包
查看>>
Docker零基础入门指南(四):Docker容器使用
查看>>
React 深入系列4:组件的生命周期
查看>>
Mybatis之设计模式之迭代器模式
查看>>
房间号生成器
查看>>