原文:https://blog.csdn.net/yapingxin/article/details/7288325

对于不太了解.Net的人,如果想要了解.Net,我必须给他介绍P/Invoke。P/Invoke是什么呢?简单地说,就是在.Net中调用本地代码(Native code)的一种解决方案。所谓“本地代码”是相对于托管代码(Managed code)来说的。

P/Invoke实在是一个非常棒(awesome)的特性。本来,.Net 这项技术充分印证了托管程序(Managed program)的种种好处,但是它不够“底层”。可是,这又有什么关系呢?我们有P/Invoke!这样,托管代码的优势和调用本地API的需求就无缝地融合在一起了。

我经常在论坛里看到一些新手提的这种问题:“我刚刚学会了C#,觉得它非常棒,很方便。我的问题是:我能用它调用短信猫(SMS Modem)厂商提供的接口API吗?这些接口API可是C++的耶~~”……OK,现在一旦你了解到了P/Invoke,你就可以完全打消这方面的顾虑了。

闲言少叙,来看我们的例子。

我们的例子是:把一个C语言写的函数封装到一个动态链接库里面,然后在一个C#程序中很方便地调用它。

实现这样的一个例子对很多人来说真是意义重大,从此可以不再担心.Net不够“底层”了。

先看我们的C语言函数:

int sum(int a, int b)
{
return a + b;
}

够简单吧。

一、为动态链接库暴露出函数接口

现在我们决定把它封装到一个动态链接库里面。为了让它能封装到动态链接库里面,我们给这个函数申明的前面加上这个:

__declspec(dllexport)

源代码就变成了这样的:

__declspec(dllexport) int sum(int a, int b)
{
return a + b;
}

二、编译,得到动态链接库

然后,我们利用Visual C++自带的命令行工具cl、link将它封装成动态链接库。假设文件名为Test.c,我们希望得到Test.dll,命令如下:

cl /c Test.c
link /dll Test.obj

我们也可以用gcc来编译得到Test.dll。命令如下:

gcc -shared -o Test.dll Test.c

现在我们就得到了Test.dll。

注:从Test.c得到Test.dll的办法很多,想详细了解的话请阅读一下两篇小文:

将C语言源代码编译成动态链接库 http://blog.csdn.net/xinyaping/article/details/7284899
Visual C++ 2010 Express Tips: 用 C 和 C++ 创建动态链接库 http://blog.csdn.net/xinyaping/article/details/7288164

三、在C#中通过P/Invoke调用Test.dll中的sum()方法

P/Invoke很简单。请看下面这段简单的C#代码:

// -----------------------------------------------------------------------
// <copyright file="Program.cs" company="Yaping Xin">
// P/Invoke example.
// </copyright>
// ----------------------------------------------------------------------- namespace Invoke
{
using System;
using System.Runtime.InteropServices; /// <summary>
/// .Net P/Invoke example.
/// </summary>
internal class Program
{
/// <summary>
/// Entry point of the application.
/// </summary>
/// <param name="args">Console arguments.</param>
internal static void Main(string[] args)
{
int result = Sum(, );
Console.WriteLine("DLL func execute result: {0}", result);
} /// <summary>
/// Call method int sum(int, int) defined in Test.dll
/// </summary>
/// <param name="a">parameter a</param>
/// <param name="b">parameter b</param>
/// <returns>sum of a and b</returns>
[DllImport("Test.dll", EntryPoint = "sum")]
private static extern int Sum(int a, int b);
}
}

上面这段代码够简单吧。除去注释,除去控制台输出,除去七零八碎的部分,剩下的东西就是这个了:

[DllImport("Test.dll", EntryPoint = "sum")]
private static extern int Sum(int a, int b);

这个就是大名鼎鼎的P/Invoke。注意在这里我故意用了一个和C语言源代码中不一样的函数名Sum。C语言源代码中的函数名是sum,如果C#也用sum这个函数名,那句DLLImport就可以这样写了:

[DllImport("Test.dll")]

在这里不过是向您展示一下当C#中的函数名和DLL中的函数名不一致时,可以通过EntryPoint来进行映射(Mapping)。

编译并执行这段C#程序,执行时别忘了把Test.dll拷贝到执行目录中。结果当然是我们所预期的:

例子很简单,意义不简单。

参考文献:

将C语言源代码编译成动态链接库 http://blog.csdn.net/xinyaping/article/details/7284899
Visual C++ 2010 Express Tips: 用 C 和 C++ 创建动态链接库 http://blog.csdn.net/xinyaping/article/details/7288164
An Introduction to P/Invoke and Marshaling on the Microsoft .NET Compact Frameworkhttp://msdn.microsoft.com/en-us/library/aa446536.aspx
Essential P/Invoke http://www.codeproject.com/Articles/12121/Essential-P-Invoke
.Net可以做什么 http://blog.csdn.net/xinyaping/article/details/6722015
---------------------
作者:YapingXin
来源:CSDN
原文:https://blog.csdn.net/yapingxin/article/details/7288325
版权声明:本文为博主原创文章,转载请附上博文链接!

[转]在C#中调用C语言函数(静态调用Native DLL,Windows & Microsoft.Net平台)的更多相关文章

  1. keil or c51 汇编调用c语言函数 容易忽视的问题

    最近,在用keil 写一个小程序时,想实践一下从汇编调用 C语言函数,我们都知道C语言调用汇编函数讨论得较多,但反过来,从汇编中调用C语言的函数未见深入分析:在开始的时候,还是忽视了一个问题,就是对现 ...

  2. 实际项目开发过程中常用C语言函数的9大用法

    C语言是当中最广泛的计算机编程语言,是所有计算机编程语言的祖先,其他计算机编程语言包括当前流行的Java语言,都是用C语言实现的,C语言是编程效率最高的计算机语言,既能完成上层应用开发,也能完成底层硬 ...

  3. Matlab调用C语言函数

    Matlab调用C语言函数 如果我有一个用C语言写的函数,实现了一个功能,如一个简单的函数:double add(double x, double y) { return x + y ;}现在我想要在 ...

  4. 从linux0.11中起动部分代码看汇编调用c语言函数

    上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...

  5. c++中使用c语言函数

    在c++中使用c语言的函数时候,该函数必须在c文件中声明extern "C"才可以使用 如:extern "C" c_function_name(int, in ...

  6. python 调用 C语言函数

    python可以直接调用C语言的函数,本文记录用ctypes调用c语言的方法. test.c #include <stdio.h> int test(char *temp) { print ...

  7. 在Linux上实现Python调用C语言函数

    一般思路 Python中内置ctypes库,需调用c编译成的.so文件来实现函数调用. 假设我们所需调用的c文件名为test.c,文件里有我们需要的函数func(x,y). 将.c文件编译成 .so文 ...

  8. java jni 调用c语言函数

    今日在hibernate源代码中遇到了native关键词,甚是陌生,就查了点资料,对native是什么东西有了那么一点了解,并做一小记. native关键字说明其修饰的方法是一个原生态方法,方法对应的 ...

  9. c扩展调用php的函数(调用实现php函数的c函数)

    上一次是写的c扩展调用c的标准函数,但是只能调用头文件中申明的函数,今天来说下c扩展调用实现php函数的c函数,比方说,c扩展要用到php中ip2long这个函数,但是c不可能去php中调用,肯定是去 ...

随机推荐

  1. spring boot 多数据源加载原理

    git代码:https://gitee.com/wwj912790488/multiple-data-sources DynamicDataSourceAspect切面 必须定义@Order(-10) ...

  2. CP防火墙排错装逼三件套

    1.tcpdump 通常用来抓包处理经过网卡的交互包 [Expert@BJ-OFFICE-GW:0]# tcpdump -nni any host 10.158.1.100 -w /var/log/t ...

  3. QP简介

    QP简介 QP(Quantum Platform)是一个轻量级的.开源的.基于状态机的.事件驱动型应用程序框架.这个框架包括四部分: 事件处理器(QEP): 轻量级的事件驱动框架(QF): 任务调度微 ...

  4. Mac Tab自动补全键

    最近入手一个Mac(Mac 2019版本),在使用终端时,发现不能使用Tab键自动补全代码,网络搜寻下,发现这里有个方法,记录下,免得自己忘记: 1 / 首先找到这个图标 2 / 输入命令 nano ...

  5. 【题解】LOJ6060 Set(线性基)

    [题解]LOJ6060 Set(线性基) orz gql 设所有数的异或和为\(S\),答案是在\(\max (x_1+S\and x_1)\)的前提下\(\min x_1\)输出\(x_1\) 转换 ...

  6. $ CometOJ-Contest\#11\ D$ $Kruscal$重构树

    正解:$Kruscal$重构树 解题报告: 传送门$QwQ$ 发现一个图上搞就很麻烦,考虑变为生成树达到原有效果. 因为在询问的时候是要求走到的点编号尽量小,发现这个时候点的编号就成为限制了,于是不难 ...

  7. 从零开始安装Redis 集群(Linux CenOS7)

    从零开始安装Redis 集群(Linux CenOS7) 使用ISO安装CentOS7虚拟机 配置静态IP(参考Mac VMware Fusion CentOS7配置静态IP) 安装vim [root ...

  8. Spring事务失效的 8 大原因,这次可以吊打面试官了!

    今天再来一篇<吊打面试官>系列,这次真的要吊打了,哈哈!(看往期吊打系列请在后台回复:吊打,我会陆续更新--) 前几天栈长不是发了一篇文章,里面有一个关于事务失效的问题: 用 Spring ...

  9. 让你彻底明白TCP三次握手,四次挥手

    今天我们来讲一下TCP的三次握手和四次挥手,先来张思维导图.  一.TCP是什么 TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流 ...

  10. 动态代理之 JDK 动态代理

    动态代理 动态代理源于设计模式中的代理模式,代理模式的主要作用就是使代理对象完成用户的请求,屏蔽用户对真实对象的访问.通过代理对象去访问目标对象来控制原对象的访问. 代理模式的最典型的应用就是 Spr ...