4234

来源:互联网 发布:淘宝怎么答题 编辑:程序博客网 时间:2024/05/17 01:01
 
找到您想要的开源软件,分享和交流
  • 软件
  • 讨论
  • 代码
  • 资讯
  • 博客
  • Android
  • WP7
当前访客身份: 游客 [ 登录 | 加入开源中国 ] 你有0新留言
raifeiraifei关注此人
关注(0) 粉丝(0) 积分(13)
这个人很懒,啥也没写
.发送留言.请教问题
博客分类
  • 工作日志(0)
  • 日常记录(0)
  • 转贴的文章(20)
阅读排行
  1. 1. 第二课,Extjs中Json的应用
  2. 2. Microsoft Enterprise Library 5.0 系列(四) Logging Application Block
  3. 3. C#程序调用非托管C++ DLL文件的方法
  4. 4. Visual Studio 2010 旗舰版免序列号安装体验
  5. 5. Visual Studio 2010为 C# 开发人员提供的新的IDE功能
  6. 6. 英文VS2010安装中文版MSDN文档方法
  7. 7. Debian5 dom0上跑Xen Debian5 lenny domU&Xen ubuntu10.04 Lucid domU--我爱你,飞一般的感觉
  8. 8. 微软一站式示例代码库 2010-05-31 新增代码示例简介
最新评论
  • @zhoujg:借鉴XAF的一个开源项目:http://openexpressapp...查看»
访客统计
  • 0
  • 7
  • 21
  • 308
  • 6892

C#程序调用非托管C++ DLL文件的方法

0人收藏此文章, 我要收藏发表于1年前 , 已有715次阅读 共0个评论

阅读: 822 评论: 4 作者: Caizhi 发表于 2010-05-31 22:15原文链接

  08年写的一篇文章,当时项目用C#开发,但是有一些希望重用之前的C++代码,于是研究了如何在C#中调用C++的DLL。

 

C++中的函数声明

view source
print?
1extern "C" __declspec(dllexport)int __stdcall testfunc(char* astr,int* a);

  

extern ”C”

  通常来说,C++编译器可能会改变函数和变量的名字,从而导致严重的链接程序问题。例如,假设使用C++编写一个DLL,当创建DLL时,Microsoft的编译器就会改变函数的名字。函数名将被设置一个前导下划线,再加上一个@符号的前缀,后随一个数字,表示作为参数传递给函数的字节数。例如,下面的函数是作为DLL的输出节中的_MyFunc@8输出的:

view source
print?
1__declspec(dllexport)LONG __stdcall MyFunc(inta, int b);

  如果用另一个供应商的工具创建了一个可执行模块,它将设法链接到一个名叫MyFunc的函数,该函数在Microsoft编译器已有的DLL中并不存在,因此链接将失败。

  使用extern “C”关键字可以使编译器按照C语言的方式编译DLL文件,即编译时不改变函数名。

 

__declspec(dllexport)

  在 32 位编译器版本中,可以使用__declspec(dllexport) 关键字从DLL导出数据、函数、类或类成员函数。__declspec(dllexport) 会将导出指令添加到对象文件中,因此不需要使用.def文件。

  若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。例如:

view source
print?
1__declspec(dllexport)void __cdecl Function1(void);

 

__stdcall

  表明被调用方清理堆栈。

 

C#中的函数声明

view source
print?
1using System.Runtime.InteropServices;
2      
3  
4public class Program
5{
6[DllImport(@"E:\Projects\testdll\debug\testdll.dll")]
7public static extern int testfunc(StringBuilder abuf,refint a);
8}

 

using System.Runtime.InteropServices;

  System.Runtime.InteropServices 命名空间提供各种各样支持 COM interop 及平台调用服务的成员,使程序可以与非托管代码进行交互操作。

 

[DllImport(“dllfile path”)]

  代码中DllImport关键字作用是告诉编译器入口点在哪里,并将打包函数捆绑在这个类中。在声明的时候还可以添加几个属性:

view source
print?
1[DllImport("MyDLL.dll",
2EntryPoint="mySum",
3CharSet=CharSet.Auto,
4CallingConvention=CallingConvention.StdCall)]

  EntryPoint: 指定要调用的 DLL 入口点。默认入口点名称是托管方法的名称 。
  CharSet: 控制名称重整和封送 String 参数的方式 (默认是UNICODE)
  CallingConvention指示入口点的函数调用约定(默认WINAPI)

  注意:必须在标记为”static”和”extern”的方法上指定”DllImport”属性。

 

数据传递方法

1.基本数据类型的传递

  函数参数和返回值可以是C#和C++的各种基本数据类型,如int, float, double, char(注意不是char*)等。
  示例:
  C#代码:

view source
print?
01using System;
02using System.Text;
03using System.Runtime.InteropServices;
04  
05class Program
06{
07    [DllImport(@"E:\Projects\testdll\debug\testdll.dll")]
08    publicstatic externint testfunc(inta,float b,double c,chard);
09  
10    staticvoid Main(string[] args)
11    {
12        inta = 1;
13        floatb = 12;
14        doublec = 12.34;
15        chard = 'A';
16        testfunc(a,b,c,d);
17        Console.ReadKey();
18    }
19}

  C++代码:

view source
print?
001<PRE class=brush:cpp minmax_bound="true"sizcache07219430890837806="5"sizset="1">#include <IOSTREAM minmax_bound="true">
002using namespace std;
003  
004extern "C"
005{
006 _declspec(dllexport)int __stdcall testfunc(inta,float b,double c,chard)
007 {
008  cout<<A minmax_bound="true"sizcache07219430890837806="5"sizset="1"><<", "<<B minmax_bound="true"sizcache07219430890837806="5"sizset="1"><<", "<<C minmax_bound="true"><<", "<<D minmax_bound="true"><<ENDL; pre < } 0;return minmax_bound="true">
009</PRE>
010<H2 minmax_bound="true">2.向DLL传入字符串</H2>
011</A><P minmax_bound="true">  C#中使用string定义字符串,将字符串对象名传给DLL。<BR minmax_bound="true">  注意:在DLL中更改字符串的值,C#中的值也会改变。<BR minmax_bound="true">  缺点:无法改变字符串的长度,建议使用第3种方法。<BR minmax_bound="true">  C#代码:</P>
012<PRE class=brush:csharp minmax_bound="true">usingSystem;
013using System.Text;
014using System.Runtime.InteropServices;
015  
016class Program
017{
018    [DllImport(@"E:\Projects\testdll\debug\testdll.dll")]
019    publicstatic externint testfunc(string a);
020  
021    staticvoid Main(string[] args)
022    {
023        string a="Hello World!";
024        testfunc(a);
025        Console.ReadKey();
026    }
027}</PRE>
028<P minmax_bound="true">  C++代码:</P>
029<PRE class=brush:cpp minmax_bound="true"sizcache07219430890837806="5"sizset="1">#include <IOSTREAM minmax_bound="true">
030using namespace std;
031  
032extern "C"
033{
034 _declspec(dllexport)int __stdcall testfunc(char* astr)
035 {
036  cout<<ASTR minmax_bound="true"><<ENDL; cout<<astr 更改字符串的数据 ; *astr="A"minmax_bound="true"><<ENDL; pre < } 0;return minmax_bound="true">
037<H3 minmax_bound="true">3.DLL传出字符串</H3>
038<P minmax_bound="true">  C#中使用StringBuilder对象创建变长数组,并设置StringBuilder的Capacity为数组最大长度。将此对象名传递给DLL,使用char*接收。<BR minmax_bound="true">  C#代码:</P>
039<PRE class=brush:csharp minmax_bound="true">usingSystem;
040using System.Text;
041using System.Runtime.InteropServices;
042  
043class Program
044{
045    [DllImport(@"E:\Projects\testdll\debug\testdll.dll")]
046    publicstatic externint testfunc(StringBuilder abuf);
047  
048    staticvoid Main(string[] args)
049    {
050        StringBuilder abuf=newStringBuilder();
051        abuf.Capacity = 100;//设置字符串最大长度
052        testfunc(abuf);
053        Console.ReadKey();
054    }
055      
056}</PRE>
057<P minmax_bound="true">  C++代码:</P>
058<PRE class=brush:cpp minmax_bound="true">#include <IOSTREAM minmax_bound="true">
059using namespace std;
060  
061extern "C"
062{
063 _declspec(dllexport)int __stdcall testfunc(char* astr)
064 {
065  *astr++='a';
066  *astr++='b';//C#中abuf随astr改变
067  *astr='\0';
068  
069  return0;
070 }
071}
072  
073  
074</PRE>
075<H3 minmax_bound="true">4.DLL传递结构体(需要在C#中重新定义,不推荐使用)</H3>
076<P minmax_bound="true">  C#中使用StructLayout重新定义需要使用的结构体。<BR minmax_bound="true">  注意:在DLL改变结构体成员的值,C#中随之改变。<BR minmax_bound="true">  C#代码:</P>
077<PRE class=brush:csharp minmax_bound="true">usingSystem;
078using System.Text;
079using System.Runtime.InteropServices;
080  
081[StructLayout(LayoutKind.Sequential)]
082public struct Point
083{
084    publicdouble x;
085    publicdouble y;
086}
087  
088class Program
089{
090    [DllImport(@"E:\Projects\testdll\debug\testdll.dll")]
091    publicstatic externint testfunc(Point p);
092  
093    staticvoid Main(string[] args)
094    {
095        Point p;
096        p.x = 12.34;
097        p.y = 43.21;
098        testfunc(p);
099        Console.ReadKey();
100    }    
101}
102  
103  
104</PRE>
105<P minmax_bound="true">C++代码:</P>
106<PRE class=brush:cpp minmax_bound="true"sizcache07219430890837806="5"sizset="1">#include <IOSTREAM minmax_bound="true">
107using namespace std;
108  
109struct Point
110{
111    doublex;
112    doubley;
113};
114  
115extern "C"
116{
117 _declspec(dllexport)int __stdcall testfunc(Point p)
118 {
119  cout<<P.X minmax_bound="true"><<", "<<P.Y minmax_bound="true"><<ENDL; pre < } 0; return minmax_bound="true"><IMG style="WIDTH: 1px; HEIGHT: 1px; maxWidth: 640px; minmaxWidth: 1px; minmaxHeight: 1px"height=1 alt="" src="http://www.cnblogs.com/Chase/aggbug/1748596.html?type=1"width=1 minmax_bound="true"><P minmax_bound="true"sizcache07219430890837806="3"sizset="44">评论: 4 <A href="http://www.cnblogs.com/Chase/archive/2010/05/31/1748596.html#pagedcomment"target=_blank minmax_bound="true">查看评论</A> <A href="http://www.cnblogs.com/Chase/archive/2010/05/31/1748596.html#commentform"target=_blank minmax_bound="true">发表评论</A></P><P minmax_bound="true"sizcache07219430890837806="3"sizset="46"><A href="http://job.cnblogs.com/offer/7427/"target=_blank minmax_bound="true">沪江网招聘ASP.NET开发工程师</A></P><HR minmax_bound="true"><P minmax_bound="true"sizcache07219430890837806="3"sizset="47">最新新闻:<BR minmax_bound="true">· <A href="http://news.cnblogs.com/n/65438/"target=_blank minmax_bound="true">当微博连通大屏幕</A><SPAN style="COLOR: gray"minmax_bound="true">(2010-06-01 12:42)</SPAN><BR minmax_bound="true">· <A href="http://news.cnblogs.com/n/65437/"target=_blank minmax_bound="true">从1.0到2.2 细数Android系统18个月历程</A><SPAN style="COLOR: gray"minmax_bound="true">(2010-06-01 12:07)</SPAN><BR minmax_bound="true">· <A href="http://news.cnblogs.com/n/65436/"target=_blank minmax_bound="true">只因有你 回眸Qzone五年成长历程</A><SPAN style="COLOR: gray"minmax_bound="true">(2010-06-01 12:04)</SPAN><BR minmax_bound="true">· <A href="http://news.cnblogs.com/n/65435/"target=_blank minmax_bound="true">谷歌手机Adsense冻结开发者账户遭质疑</A><SPAN style="COLOR: gray"minmax_bound="true">(2010-06-01 11:58)</SPAN><BR minmax_bound="true">· <A href="http://news.cnblogs.com/n/65434/"target=_blank minmax_bound="true">Chrome推送网页至手机功能视频展示</A><SPAN style="COLOR: gray"minmax_bound="true">(2010-06-01 11:55)</SPAN><BR minmax_bound="true"></P><P minmax_bound="true"sizcache07219430890837806="3"sizset="52">编辑推荐:<A href="http://www.cnblogs.com/topic/51/"target=_blank minmax_bound="true">关于Java与.NET的讨论</A><BR minmax_bound="true"></P><P minmax_bound="true"sizcache07219430890837806="3"sizset="53">网站导航:<A href="http://www.cnblogs.com"target=_blank minmax_bound="true">博客园首页</A>  <A href="http://home.cnblogs.com/"target=_blank minmax_bound="true">个人主页</A>  <A href="http://news.cnblogs.com"target=_blank minmax_bound="true">新闻</A>  <A href="http://home.cnblogs.com/ing/"target=_blank minmax_bound="true">闪存</A>  <A href="http://home.cnblogs.com/group/"target=_blank minmax_bound="true">小组</A>  <A href="http://space.cnblogs.com/q/"target=_blank minmax_bound="true">博问</A>  <A href="http://space.cnblogs.com"target=_blank minmax_bound="true">社区</A>  <A href="http://kb.cnblogs.com"target=_blank minmax_bound="true">知识库</A></P></PRE></PRE>
原文地址:http://home.oschina.net/javayou/blog/17
--

共有 0 条网友评论

尚无网友评论


    文明上网,理性发言

    文明上网,理性发言
    回到页首 | 回到评论列表
    关闭相关文章阅读
    • 2010/10/01 C#程序调用非托管C DLL文件的方法...
    • 2011/06/30 android intent隐式调用之一个应用程...
    • 2010/10/01 [CLI/C++].NET托管代码和非托管代码...
    • 2010/09/28 动态装载、调用DLL中的非托管函数
    • 2011/10/01 程序员技术练级攻略
    原创粉丝点击