4234
来源:互联网 发布:淘宝怎么答题 编辑:程序博客网 时间:2024/05/17 01:01
- 软件
- 讨论
- 代码
- 资讯
- 博客
- Android
- WP7
- 工作日志(0)
- 日常记录(0)
- 转贴的文章(20)
- 1. 第二课,Extjs中Json的应用
- 2. Microsoft Enterprise Library 5.0 系列(四) Logging Application Block
- 3. C#程序调用非托管C++ DLL文件的方法
- 4. Visual Studio 2010 旗舰版免序列号安装体验
- 5. Visual Studio 2010为 C# 开发人员提供的新的IDE功能
- 6. 英文VS2010安装中文版MSDN文档方法
- 7. Debian5 dom0上跑Xen Debian5 lenny domU&Xen ubuntu10.04 Lucid domU--我爱你,飞一般的感觉
- 8. 微软一站式示例代码库 2010-05-31 新增代码示例简介
- @zhoujg:借鉴XAF的一个开源项目:http://openexpressapp...查看»
- 0
- 7
- 21
- 308
- 6892
C#程序调用非托管C++ DLL文件的方法
阅读: 822 评论: 4 作者: Caizhi 发表于 2010-05-31 22:15原文链接
08年写的一篇文章,当时项目用C#开发,但是有一些希望重用之前的C++代码,于是研究了如何在C#中调用C++的DLL。
C++中的函数声明
1
extern
"C"
__declspec
(
dllexport
)
int
__stdcall testfunc(
char
* astr,
int
* a);
extern ”C”
通常来说,C++编译器可能会改变函数和变量的名字,从而导致严重的链接程序问题。例如,假设使用C++编写一个DLL,当创建DLL时,Microsoft的编译器就会改变函数的名字。函数名将被设置一个前导下划线,再加上一个@符号的前缀,后随一个数字,表示作为参数传递给函数的字节数。例如,下面的函数是作为DLL的输出节中的_MyFunc@8输出的:
1
__declspec
(
dllexport
)
LONG
__stdcall MyFunc(
int
a,
int
b);
如果用另一个供应商的工具创建了一个可执行模块,它将设法链接到一个名叫MyFunc的函数,该函数在Microsoft编译器已有的DLL中并不存在,因此链接将失败。
使用extern “C”关键字可以使编译器按照C语言的方式编译DLL文件,即编译时不改变函数名。
__declspec(dllexport)
在 32 位编译器版本中,可以使用__declspec(dllexport) 关键字从DLL导出数据、函数、类或类成员函数。__declspec(dllexport) 会将导出指令添加到对象文件中,因此不需要使用.def文件。
若要导出函数,__declspec(dllexport) 关键字必须出现在调用约定关键字的左边(如果指定了关键字)。例如:
1
__declspec
(
dllexport
)
void
__cdecl Function1(
void
);
__stdcall
表明被调用方清理堆栈。
C#中的函数声明
1
using
System.Runtime.InteropServices;
2
…
3
4
public
class
Program
5
{
6
[DllImport(
@"E:\Projects\testdll\debug\testdll.dll"
)]
7
public
static
extern
int
testfunc(StringBuilder abuf,
ref
int
a);
8
}
using System.Runtime.InteropServices;
System.Runtime.InteropServices 命名空间提供各种各样支持 COM interop 及平台调用服务的成员,使程序可以与非托管代码进行交互操作。
[DllImport(“dllfile path”)]
代码中DllImport关键字作用是告诉编译器入口点在哪里,并将打包函数捆绑在这个类中。在声明的时候还可以添加几个属性:
1
[DllImport(
"MyDLL.dll"
,
2
EntryPoint=
"mySum"
,
3
CharSet=CharSet.Auto,
4
CallingConvention=CallingConvention.StdCall)]
EntryPoint: 指定要调用的 DLL 入口点。默认入口点名称是托管方法的名称 。
CharSet: 控制名称重整和封送 String 参数的方式 (默认是UNICODE)
CallingConvention指示入口点的函数调用约定(默认WINAPI)
注意:必须在标记为”static”和”extern”的方法上指定”DllImport”属性。
数据传递方法
1.基本数据类型的传递
函数参数和返回值可以是C#和C++的各种基本数据类型,如int, float, double, char(注意不是char*)等。
示例:
C#代码:
01
using
System;
02
using
System.Text;
03
using
System.Runtime.InteropServices;
04
05
class
Program
06
{
07
[DllImport(
@"E:\Projects\testdll\debug\testdll.dll"
)]
08
public
static
extern
int
testfunc(
int
a,
float
b,
double
c,
char
d);
09
10
static
void
Main(
string
[] args)
11
{
12
int
a = 1;
13
float
b = 12;
14
double
c = 12.34;
15
char
d =
'A'
;
16
testfunc(a,b,c,d);
17
Console.ReadKey();
18
}
19
}
C++代码:
001
<PRE
class
=brush:cpp minmax_bound=
"true"
sizcache07219430890837806=
"5"
sizset=
"1"
>#include <IOSTREAM minmax_bound=
"true"
>
002
using
namespace
std;
003
004
extern
"C"
005
{
006
_declspec(
dllexport
)
int
__stdcall testfunc(
int
a,
float
b,
double
c,
char
d)
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"
>
using
System;
013
using
System.Text;
014
using
System.Runtime.InteropServices;
015
016
class
Program
017
{
018
[DllImport(@
"E:\Projects\testdll\debug\testdll.dll"
)]
019
public
static
extern
int
testfunc(string a);
020
021
static
void
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"
>
030
using
namespace
std;
031
032
extern
"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"
>
using
System;
040
using
System.Text;
041
using
System.Runtime.InteropServices;
042
043
class
Program
044
{
045
[DllImport(@
"E:\Projects\testdll\debug\testdll.dll"
)]
046
public
static
extern
int
testfunc(StringBuilder abuf);
047
048
static
void
Main(string[] args)
049
{
050
StringBuilder abuf=
new
StringBuilder();
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"
>
059
using
namespace
std;
060
061
extern
"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
return
0;
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"
>
using
System;
078
using
System.Text;
079
using
System.Runtime.InteropServices;
080
081
[StructLayout(LayoutKind.Sequential)]
082
public
struct
Point
083
{
084
public
double
x;
085
public
double
y;
086
}
087
088
class
Program
089
{
090
[DllImport(@
"E:\Projects\testdll\debug\testdll.dll"
)]
091
public
static
extern
int
testfunc(Point p);
092
093
static
void
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"
>
107
using
namespace
std;
108
109
struct
Point
110
{
111
double
x;
112
double
y;
113
};
114
115
extern
"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>
- 吉日嘎啦通用权限管理系统解读及重构升华--高度封装的编辑窗体 »
共有 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 程序员技术练级攻略
- 4234
- NKOJ 4234 三角分形
- Map的Get方法的使用
- 2012年软考
- 加密解密
- 176. Genius is nothing but labor and diligence. 天才不过是勤奋而已
- 存储过程的使用
- 4234
- CComboBox 下拉列表删除最后一个选项时,不为空,必须要调用SetCurSel(-1)才可以清空。
- ubuntu linux 下 adb 连接andoid 设备失败的处理以及刷机
- HDU---1114题Piggy-Bank
- 存储过程
- 二十年后的回眸(5)——一部单车闯天下
- 常用的c_c++代码
- CFileFind类
- 让970的ADB运行在root权限下的方法