C#调用C++的程序.doc_第1页
C#调用C++的程序.doc_第2页
C#调用C++的程序.doc_第3页
C#调用C++的程序.doc_第4页
C#调用C++的程序.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C# 调用 C+ 程序2010-11-16 08:54:43|分类: .NET技术 |标签: |字号大中小订阅 一个简单的案例,学习一下如何通过C#来调用用C+开发的DLL中提供的API.1. 建立一个C#控制台工程,主要用于调试。2. 在解决方案中添加一个新的空工程(VC+的)。3. 创建后的工程如下图所示:4. 在C+工程中添加一个源文件到Source Files文件夹(xxx.c or xxx.cpp),如:MyMath.cpp内容如下:#includeextern C _declspec(dllexport) int mySum(int a, int b, int *c) *c = a + b; return *c; 5. 右键点击C+工程,在属性中的General-Configuration Type 选择 Dynamic Library (.dll)。6. 这里还要注意的是为了编译生成的dll文件能被c# 工程导入你需要Common Language Runtime support 选择Common Language Runtime Support (/clr)这项,否则编译的dll不能用到c#工程当中。7.build C+工程(你也可以用命令行CL.exe来编译文件)。之后,有很多人就直接想当然的跑到c+工程下面的Debug文件夹里去找xxx.dll文件,结果只看到ermediate.manifest这样的文件失望而归。其实编译后真正的dll文件是在解决方案的Debug文件夹下面。在本例子里,是放在目录D:C+ProjectCImportDemoDebug下,而不是目录D:C+ProjectCImportDemoCDllProjectDebug下。8.在c#工程的引用中导入xxx.dll。在c#主文件中键入如下代码:我这里的xxx = CDllProject.dllusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Runtime.InteropServices;namespace CImportDemo class Program DllImport(CDllProject.dll, EntryPoint = mySum, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall) public static extern int mySum(int a, int b, ref int c); static void Main(string args) int c = 0; Console.WriteLine(mySum(8, 9, ref c); Console.Read(); 9. 最后你会看到运行结果:17。参考:/john-cncn/articles/1136417.html这篇文章没有什么新意,在2004年的时候就有人写过那时候VS还只是2003版,而且网络上也有很多转来转去的文章,其实一共那么两三篇。其实我也是从那里学来的,只不过中间经历的一些郁闷,因为那些文章没有提到一些注意的事项确是很烦人。1. 建立一个C#控制台工程,主要用于调试。2. 在解决方案中添加一个新的空工程(VC+的)。3. 添加一个源文件到Source Files文件夹(xxx.c or xxx.cpp)。4. 加入这行代码#include extern C _declspec(dllexport) int mySum(int a,int b,int *c) *c=a+b; return *c; 由于原来的文章没有提,导致我缺了#include 而编译出错,花了点时间修正这问题。5. 右键点击C+工程,在属性中的General-Configuration Type 选择 Dynamic Library (.dll)。这里还要注意的是为了编译生成的dll文件能被c# 工程导入你需要Common Language Runtime support 选择Common Language Runtime Support (/clr)这项,否则编译的dll不能用到c#工程当中。6. build C+工程(你也可以用命令行CL.exe来编译文件)。之后,有很多人就直接向当然的跑到c+工程下面的Debug文件夹里去找xxx.dll文件,结果只看到ermediate.manifest这样的文件失望而归。其实编译后真正的dll文件是在解决方案的Debug文件夹下面。7. 在c#工程的引用中导入xxx.dll。在c#主文件中键入如下代码:我这里的xxx = CCodeDllusing System;using System.Collections.Generic;using System.Text;using System.Runtime.InteropServices;namespace TestEmbedCCalling class Program DllImport(CCodeDll.dll, EntryPoint = mySum, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall) public static extern int mySum(int a, int b, ref int c); static void Main(string args) int c = 0; Console.WriteLine(mySum(2, 3, ref c); Console.Read(); 最后你会看到运行结果:5。请注意绿色字体内容,祝你好运。 考虑到将来有可能需要用C#调用C+的程序,先实验一下。先准备下C+程序:#include#includeintmain()printf(hi);intv1,v2;std:cinv1;v2=v1*2;std:coutv2std:endl;用C#调用:大气象 usingSystem;usingSystem.Data;usingSystem.Configuration;usingSystem.Web;usingSystem.Web.Security;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Web.UI.WebControls.WebParts;usingSystem.Web.UI.HtmlControls;usingSystem.Diagnostics;publicpartialclass_Default:System.Web.UI.PageprotectedvoidPage_Load(objectsender,EventArgse)Bind();privatevoidBind()Processp=newProcess();p.StartInfo.FileName=F:codecppFirstCmddebugFirstCmd.exe;/p.StartInfo.Arguments=;p.StartInfo.UseShellExecute=false;p.StartInfo.RedirectStandardInput=true;p.StartInfo.RedirectStandardOutput=true;p.StartInfo.CreateNoWindow=false;p.Start();/p.StandardInput.WriteLine(2);stringoutput=p.StandardOutput.ReadToEnd();Response.Write(output);/if(p.HasExited)/p.Kill();昨天晚上想做个实验,实现在C#程序中调用C+写的函数。代码很简单,却总是提示在DLL文件中无法找到入口点:“Unable to find an entry point named Add in DLL Lib.dll.”,弄了一晚上都没搞定,很是郁闷。今天在网上查了很多资料,终于整出来了。下面是在网上转载的东东。一、C+中extern “C”含义深层探索1.引言C+语言的创建初衷是“a better C”,但是这并不意味着C+中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C+保留了一部分过程式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C+毕竟是一种面向对象的程序设计语言,为了支持函数的重载,C+对全局函数的处理方式与C有明显的不同。2.从标准头文件说起某企业曾经给出如下的一道面试题:面试题为什么标准头文件都有类似以下的结构?#ifndef _INCvxWorksh#define _INCvxWorksh #ifdef _cplusplusextern C #endif /*.*/ #ifdef _cplusplus#endif #endif /* _INCvxWorksh */分析显然,头文件中的编译宏“#ifndef _INCvxWorksh、#define _INCvxWorksh、#endif” 的作用是防止该头文件被重复引用。那么#ifdef _cplusplusextern C #endif #ifdef _cplusplus#endif的作用又是什么呢?我们将在下文一一道来。3.深层揭密extern Cextern C 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。被extern C限定的函数或变量是extern类型的;extern是C/C+语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:extern int a;仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编译生成的目标代码中找到此函数。与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。被extern C修饰的变量和函数是按照C语言方式编译和连接的;未加extern “C”声明时的编译方式首先看看C+中对类似C的函数是怎样编译的。作为一种面向对象的语言,C+支持函数重载,而过程式语言C则不支持。函数被C+编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:void foo( int x, int y );该函数被C编译器编译后在符号库中的名字为_foo,而C+编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C+就是靠这种机制来实现函数重载的。例如,在C+中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。同样地,C+中的变量除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以.来区分。而本质上,编译器在进行编译时,与函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。未加extern C声明时的连接方式假设在C+中,模块A的头文件如下:/ 模块A头文件moduleA.h#ifndef MODULE_A_H#define MODULE_A_Hint foo( int x, int y );#endif在模块B中引用该函数:/ 模块B实现文件moduleB.cpp#include moduleA.hfoo(2,3);实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!加extern C声明后的编译和连接方式加extern C声明后,模块A的头文件变为:/ 模块A头文件moduleA.h#ifndef MODULE_A_H#define MODULE_A_Hextern C int foo( int x, int y );#endif在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:(1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。如果在模块A中函数声明了foo为extern C类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):实现C+与C及其它语言的混合编程。明白了C+中extern C的设立动机,我们下面来具体分析extern C通常的使用技巧。4.extern C的惯用法(1)在C+中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:extern C#include cExample.h而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern C声明,在.c文件中包含了extern C时会出现编译语法错误。笔者编写的C+引用C函数例子工程中包含的三个文件的源代码如下:/* c语言头文件:cExample.h */#ifndef C_EXAMPLE_H#define C_EXAMPLE_Hextern int add(int x,int y);#endif/* c语言实现文件:cExample.c */#include cExample.hint add( int x, int y )return x + y;/ c+实现文件,调用add:cppFile.cppextern C #include cExample.hint main(int argc, char* argv)add(2,3); return 0;如果C+调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern C 。(2)在C中引用C+语言中的函数和变量时,C+的头文件需添加extern C,但是在C语言中不能直接引用声明了extern C的该头文件,应该仅将C文件中将C+中定义的extern C函

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论