P/Invoke:C#调用C++

P/Invoke的全称是Platform Invoke (平台调用) 它实际上是一种函数调用机制通 过P/Invoke我们就可以调用非托管DLL中的函数。

P/Invoke依次执行以下操作:

1. 查找包含该函数的非托管DLL

2. 将该非托管DLL加载到内存中

3. 查找函数在内存中的地址并将其参数按照函数的调用约定压栈

4. 将控制权转移给非托管函数

步骤:

1. 建立"Win32 Project -> DLL" application。

2. 编C++类及调用函数:

"cpp.h"

1 class Student
2 {
3 public:
4     int getNumber(int i);
5 };
6
7 extern "C"   __declspec(dllexport)  int _stdcall  getStuNumber(int i);

"cpp.cpp"

 1 #include "stdafx.h"
 2 #include "Cpp.h"
 3
 4 int Student::getNumber(int i)
 5 {
 6     return i+100;
 7 }
 8
 9 extern "C" _declspec(dllexport)  int _stdcall  getStuNumber(int i)
10
11 {
12     Student stu;
13     return stu.getNumber(i);
14 }

extern "C" :  extern "C"使得在C++中使用C编译方式成为可能。在“C++”下定义“C”函数,需要加extern “C”关键词。用extern "C"来指明该函数使用C编译方式。

__declspec(dllexport):    将一个函数声名为导出函数。

 _stdcall :以标准方式调用,起到查找入口点的作用。

3. 编C#调用

 1 using System;
 2 using System.Runtime.InteropServices;
 3 namespace CSharp
 4 {
 5     public class CppInvoke
 6     {
 7         [DllImport("CPP.dll", CallingConvention=CallingConvention.StdCall)] 8         public static extern int getStuNumber(int i);
 9     }
10
11     class Program
12     {
13         static void Main(string[] args)
14         {
15             int j = CppInvoke.getStuNumber(100);
16             Console.WriteLine(j);
17             Console.ReadLine();
18         }
19     }
20 }

DllImport: 用来标识该方法是非托管的代码方法,在编译器编译的时候它能够正确的认识出被该特性标记的是外来代码段。当到达程序运行的时候,也能够正确的认识出该代码是引用非托管的代码,这样CLR会去加载非托管DLL文件,然后查找到入口点进行调用。

CallingConvention:在平台调用的过程中起到查找入口点的作用,在托管代码进行非托管代码入口点查找时,会通过CallingConvention中的值进行确认非托管入口点的调用约定。此项也可省略。

4. 设置输出路径,调试选项:

a. 将C++Project的“output directory” 和C#project的“output path” 设置在同一目录,这样以遍 C#程序能够找到C++ DLL.

b. 选上 "Enable unmanaged code debugging"选项,以便调试时候跟踪到C++程序。

好了。可以执行程序,看执行结果了。

时间: 2024-10-14 07:13:35

P/Invoke:C#调用C++的相关文章

java.lang.reflect.InvocationHandler中invoke()方法调用时机

Java中动态代理的实现,关键就是这两个东西:Proxy.InvocationHandler,下面从InvocationHandler接口中的invoke方法入手,简单说明一下Java如何实现动态代理的. invoke方法的完整形式如下: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable       {              method.invoke(obj, args);  

.netcore在linux下使用P/invoke方式调用linux动态库

.netcore下已经实现了通过p/invoke方式调用linux的动态链接库(*.so)文件 1 [DllImport(@"libdl.so.2")] 2 public static extern IntPtr dlopen(string filename, int flags); 3 [DllImport("libdl.so.2")] 4 public static extern IntPtr dlsym(IntPtr handle, string symbol

P/Invoke .NET调用win32API

项目:无线无源测温软件系统 项目中,用到使用P/Invoke在.NET调用win32API,实现对ini配置文件的读写功能!因为有一些配置信息需要保存下来,以便在下一次启动程序完成初始化,这实际上是一种类持久化.将 一些信息写入INI文件(initialization file)中,可完成简单的持久化支持. Windows提供了API接口用于操作INI文件,其支持的INI文件格式一般如下: =============================== [Section1] Key11=valu

java反射机制之Method invoke执行调用方法例子

昨天在群里跟大家讨论了下java反射调用可变参数的问题,这个问题起因是我们需要反射调用另一个部门提供的方法,我同事说java不能反射调用可变参数的方法,于是我写了个demo证明了他这个观点的错误.但是测试过程中,有一点我不明白,就是反射调用可变参数的方法时,为什么一定要保证传入的参数数组长度为1,在群里跟大家讨论了很多,没有得到确切的答案,参照网上大牛写的东西和我自己跟源码的过程,记录如下: 1.两个类,一个父类,一个子类 [java] view plain copy print? packag

Winform 关于委托与Invoke和Begin Invoke的使用

这方面的文章已经写得很详细了,特地摘引两篇文章 http://www.cnblogs.com/c2303191/articles/826571.html http://www.cnblogs.com/EasonLeung/p/3683492.html http://www.cnblogs.com/Rustle/articles/11301.aspx 然后我想把自己的理解记录下来,做一个笔记. 1.Control的Invoke和BeginInvoke的委托方法是在主线程,即UI线程上执行的,异步是

反射机制--调用构造函数和成员方法、制作帮助文档

今天学习了关于反射的相关知识,通过反射可以找到类中的构造方法和所有的成员方法.而并不了解这个类的构造的人可以很方便的运用反射机制. 掌握发射主要了解这几个类,类位于java.long.reflect包中: Class类:代表一个 类 Constructor类:代表累的构造方法 Field类:代表类中的成员变量 Method类:代表类的方法 import java.lang.reflect.*; /** 这是一个反射机制的例子实例,包括如何利用反射找到无参.有参的构造方法,以及其他方法. @aut

C#中Invoke的用法

在用.NET Framework框架的WinForm构建GUI程序界面时,如果要在控件的事件响应函数中改变控件的状态,例如:某个按钮上的文本原先叫"打开",单击之后按钮上的文本显示"关闭",初学者往往会想当然地这么写: void ButtonOnClick(object sender,EventArgs e) { button.Text="关闭"; } 这样的写法运行程序之后,可能会触发异常,异常信息大致是"不能从不是创建该控件的线程调

C++如何调用C#开发的dll

序言 本文介绍一个C++如何调用C#开发的dll实例. 前言 C++编写的程序为非托管代码,C#编写的程序为托管代码.托管代码虽然提供了其他开发平台没有的许多优势,但由于前期系统及历史版本很多使用的是非托管代码编写的程序,所以CLR提供了一些机制,允许在应用程序中同时包含托管和非托管代码.具体说分为以下三种: 托管代码能调用DLL中的非托管函数.通过P/Invoke(Platform Invoke)机制调用DLL中的函数,如Kernel32.dll等. 托管代码可以使用现有COM组件(服务器).

C# Invoke 使用

如果使用多线程,应该会遇到这样的一个问题,在子线程中想调用主线程中(Form1)控件,提示报错! 可以使用Invoke方法调用. this.Invoke(new MethodInvoker(() => { this.rTxtLog.AppendText("在线程内调用主线程中控件 " + Environment.NewLine); }));

java黑魔法-反射机制-02-通过Java反射调用其他类方法

package com.aaron.reflect; import java.lang.reflect.Method; import java.lang.reflect.InvocationTargetException; /** * Created by IntelliJ IDEA. * File: TestRef.java * User: leizhimin * Date: 2008-1-28 14:48:44 */ public class TestRef { //直接 foo.outIn