如何在C#的程序中调用C++?求大神帮助

作者&投稿:赏秀 (若有异议请与网页底部的电邮联系)
c#里面如何调用c++里面的类~

首先:可以调用
C#调用C++类库的基础类为: System.Runtime.InteropServices;

专门用于引入DLL的类.
语法为
[DllImport("DLL位置")]
private static extern int Sum(int a, int b); //函数描述
注意:这个函数是您得预先知道了

DLL的位置得位于您EXE程序的同一目录,如果不是同一目录.那必然是系统直接能够找到的位置.例如System32等

把C++代码编译成DLL,然后在C#中调用从这个DLL中露出来的函数即可。

参考

如何用VC编写dll文件
http://zhidao.baidu.com/question/3918705.html

C#使用技巧--调用DLL
http://www.window07.com/dev/code/net/2006-3-24/k105979.htm

api 函数是构筑windws应用程序的基石,每一种windows应用程序开发工具,它提供的底层函数都间接或直接地调用了windows api函数,同时为了实现功能扩展,一般也都提供了调用windowsapi函数的接口, 也就是说具备调用动态连接库的能力。visual c#和其它开发工具一样也能够调用动态链接库的api函数。.net框架本身提供了这样一种服务,允许受管辖的代码调用动态链接库中实现的非受管辖函数, 包括操作系统提供的windows api函数。它能够定位和调用输出函数,根据需要,组织其各个参数(整型、字符串类型、数组、和结构等等)跨越互操作边界。 下面以c#为例简单介绍调用api的基本过程: 动态链接库函数的声明 动态链接库函数使用前必须声明,相对于vb,c#函数声明显得更加罗嗦,前者通过 api viewer粘贴以后,可以直接使用,而后者则需要对参数作些额外的变化工作。 动态链接库函数声明部分一般由下列两部分组成,一是函数名或索引号,二是动态链接库的文件名。 譬如,你想调用user32.dll中的messagebox函数,我们必须指明函数的名字messageboxa或messageboxw,以及库名字 user32.dll,我们知道win32 api对每一个涉及字符串和字符的函数一般都存在两个版本,单字节字符的ansi版本和双字节字符的unicode版本。 下面是一个调用api函数的例子: [dllimport("kernel32.dll", entrypoint="movefilew", setlasterror=true, charset=charset.unicode, exactspelling=true, callingconvention=callingconvention.stdcall)] public static extern bool movefile(string src, string dst); 其中入口点entrypoint标识函数在动态链接库的入口位置,在一个受管辖的工程中,目标函数的原始名字和序号入口点不仅标识一个跨越互操作界限的函数。而且,你还可以把这个入口点映射为一个不同的名字,也就是对函数进行重命名。重命名可以给调用函数带来种种便利,通过重命名,一方面我们不用为函数的大小写伤透脑筋,同时它也可以保证与已有的命名规则保持一致,允许带有不同参数类型的函数共存,更重要的是它简化了对ansi和unicode版本的调用。charset用于标识函数调用所采用的是unicode或是ansi版本,exactspelling=false将告诉编译器,让编译器决定使用 unicode或者是ansi版本。其它的参数请参考msdn在线帮助. 在c#中,你可以在entrypoint域通过名字和序号声明一个动态链接库函数,如果在方法定义中使用的函数名与dll入口点相同,你不需要在entrypoint域显示声明函数。否则,你必须使用下列属性格式指示一个名字和序号。 [dllimport("dllname", entrypoint="functionname"] [dllimport("dllname", entrypoint="#123"] 值得注意的是,你必须在数字序号前加“#” 下面是一个用msgbox替换messagebox名字的例子: using system.runtime.interopservices; public class win32 { [dllimport("user32.dll", entrypoint="messagebox"] public static extern int msgbox(int hwnd, string text, string caption, uint type); } 许多受管辖的动态链接库函数期望你能够传递一个复杂的参数类型给函数,譬如一个用户定义的结构类型成员或者受管辖代码定义的一个类成员,这时你必须提供额外的信息格式化这个类型,以保持参数原有的布局和对齐。 c# 提供了一个structlayoutattribute类,通过它你可以定义自己的格式化类型,在受管辖代码中,格式化类型是一个用 structlayoutattribute说明的结构或类成员,通过它能够保证其内部成员预期的布局信息。布局的选项共有三种: 布局选项 描述 layoutkind.automatic 为了提高效率允许运行态对类型成员重新排序。 注意:永远不要使用这个选项来调用不受管辖的动态链接库函数。 layoutkind.explicit 对每个域按照fieldoffset属性对类型成员排序 layoutkind.sequential 对出现在受管辖类型定义地方的不受管辖内存中的类型成员进行排序。 传递结构成员 下面的例子说明如何在受管辖代码中定义一个点和矩形类型,并作为一个参数传递给user32.dll库中的ptinrect函数, 函数的不受管辖原型声明如下: bool ptinrect(const rect *lprc, point pt); 注意你必须通过引用传递rect结构参数,因为函数需要一个rect的结构指针。 [c#] using system.runtime.interopservices; [structlayout(layoutkind.sequential)] public struct point { public int x; public int y; } [structlayout(layoutkind.explicit] public struct rect { [fieldoffset(0)] public int left; [fieldoffset(4)] public int top; [fieldoffset(] public int right; [fieldoffset(12)] public int bottom; } class win32api { [dllimport("user32.dll"] public static extern bool ptinrect(ref rect r, point p); } 类似你可以调用getsysteminfo函数获得系统信息: ? using system.runtime.interopservices; [structlayout(layoutkind.sequential)] public struct system_info { public uint dwoemid; public uint dwpagesize; public uint lpminimumapplicationaddress; public uint lpmaximumapplicationaddress; public uint dwactiveprocessormask; public uint dwnumberofprocessors; public uint dwprocessortype; public uint dwallocationgranularity; public uint dwprocessorlevel; public uint dwprocessorrevision; } [dllimport("kernel32"] static extern void getsysteminfo(ref system_info psi); system_info psi = new system_info(); getsysteminfo(ref psi); 类成员的传递 同样只要类具有一个固定的类成员布局,你也可以传递一个类成员给一个不受管辖的动态链接库函数,下面的例子主要说明如何传递一个sequential顺序定义的mysystemtime类给user32.dll的getsystemtime函数, 函数用c/c++调用规范如下: void getsystemtime(systemtime* systemtime); 不像传值类型,类总是通过引用传递参数. [c#] [structlayout(layoutkind.sequential)] public class mysystemtime { public ushort wyear; public ushort wmonth; public ushort wdayofweek; public ushort wday; public ushort whour; public ushort wminute; public ushort wsecond; public ushort wmilliseconds; } class win32api { [dllimport("user32.dll"] public static extern void getsystemtime(mysystemtime st); } 回调函数的传递: 从受管辖的代码中调用大多数动态链接库函数,你只需创建一个受管辖的函数定义,然后调用它即可,这个过程非常直接。 如果一个动态链接库函数需要一个函数指针作为参数,你还需要做以下几步: 首先,你必须参考有关这个函数的文档,确定这个函数是否需要一个回调;第二,你必须在受管辖代码中创建一个回调函数;最后,你可以把指向这个函数的指针作为一个参数创递给dll函数,. 回调函数及其实现: 回调函数经常用在任务需要重复执行的场合,譬如用于枚举函数,譬如win32 api 中的enumfontfamilies(字体枚举), enumprinters(打印机), enumwindows (窗口枚举)函数. 下面以窗口枚举为例,谈谈如何通过调用 enumwindow 函数遍历系统中存在的所有窗口 分下面几个步骤: 1. 在实现调用前先参考函数的声明 bool enumwindows(wndenumproc lpenumfunc, lparmam iparam) 显然这个函数需要一个回调函数地址作为参数. 2. 创建一个受管辖的回调函数,这个例子声明为代表类型(delegate),也就是我们所说的回调,它带有两个参数hwnd和lparam,第一个参数是一个窗口句柄,第二个参数由应用程序定义,两个参数均为整形。 当这个回调函数返回一个非零值时,标示执行成功,零则暗示失败,这个例子总是返回true值,以便持续枚举。 3. 最后创建以代表对象(delegate),并把它作为一个参数传递给enumwindows 函数,平台会自动地 把代表转化成函数能够识别的回调格式。 using system; using system.runtime.interopservices; public delegate bool callback(int hwnd, int lparam); public class enumreportapp { [dllimport("user32"] public static extern int enumwindows(callback x, int y); public static void main() { callback mycallback = new callback(enumreportapp.report); enumwindows(mycallback, 0); } public static bool report(int hwnd, int lparam) { console.write("窗口句柄为"; console.writeline(hwnd); return true; } } 指针类型参数传递: 在windows api函数调用时,大部分函数采用指针传递参数,对一个结构变量指针,我们除了使用上面的类和结构方法传递参数之外,我们有时还可以采用数组传递参数。 下面这个函数通过调用getusername获得用户名 bool getusername( lptstr lpbuffer, // 用户名缓冲区 lpdword nsize // 存放缓冲区大小的地址指针 ); [dllimport("advapi32.dll", entrypoint="getcomputername", exactspelling=false, setlasterror=true)] static extern bool getcomputername ( [marshalas(unmanagedtype.lparray)] byte[] lpbuffer, [marshalas(unmanagedtype.lparray)] int32[] nsize ); 这个函数接受两个参数,char * 和int *,因为你必须分配一个字符串缓冲区以接受字符串指针,你可以使用string类代替这个参数类型,当然你还可以声明一个字节数组传递ansi字符串,同样你也可以声明一个只有一个元素的长整型数组。

请问在c语言中如何输出百分数?
答:把需要输出的数字乘以100再输出一个百分号 比如:double a=0.5555555;printf("输出一个百分数%f%%\n",a*100);注意:在printf里百分号也要使用%%转义。include <stdio.h> int main (void) { float r=0.1523;printf ("%.2f%%\n",r*100);getch ();return 0;} ...

如何将在c语言中生成的数据保存到文本文件中?
答:主要通过fprintf格式化输出函数实现,主要代码如下,//程序功能,将10 12.345000 testinfo 写入test.txt文件 include <stdio.h> int main(int argc, char *argv[]){ FILE *pf=NULL;int m=10;float f=12.345;char str[20]="testinfo";pf=fopen("test.txt", "w" );//假设test.txt文件为...

在c语言中如何表示一个三位数的各位数
答:三位数记为int n 建3个int变量 a b c 分别表示百位十位个位上的数字 a=n/100;b=(n-a*100)/10;c=(n-a*100-b*10);例如:include <stdio.h> main(){ int a[3];int i =0;int j;int numb = 123;while(numb!bai=0){ du a[i]= numb%10;numb = numb/10;i++;} for(j=...

在C语言中如何用最简洁的方式表示出三个数中的最大数,最小数,中间数...
答:include"iostream.h"int main(){ int x,y,z;int min,max,mid;printf("请输入三个数:");scanf("%d %d %d",&x,&y,&z);min=(x>y?y:x)>z?z:(x>y?y:x);max=(x>y?x:y)>z?(x>y?x:y):z;if((x>min) && (x<max)) mid=x;else if((y>min) && (y<max)) mid=...

在c语言中如何打出\n这个符号?
答:您好,很高兴回答您的问题。在c语言中,输入任何内容都可以根据字面含义来进行输入。比如要输入\n,那么就直接输入一个\、一个n就可以达到要求。若是要表达显示出\n,并且又是在双引号括起来的字符中,那么就需要先输入表示转义字符标志的\,然后再输入\和n,也可以得到。若是要表达出\n的含义,我们...

在C语言中如何判断输入的是否为英文字母
答::#include <ctype.h> isalnum() 用来判断一个字符是否为英文字母或数字,相当于 isalpha(c) || isdigit(c),其原型为:int isalnum(int c);【参数】c 为需要检测的字符。【返回值】若参数c 为字母或数字,若 c 为 0 ~ 9 a ~ z A ~ Z 则返回非 0,否则返回 0。注意,isalnum()...

在c语言编程中如何实现程序对文本文件中字符串进行替换及生成新的文本...
答:我以前刚学C++的时候写过一个相似的程序,如果你要的是纯C语言下的编程,那么你就参考一下,这个算法的原理是一样的,即读入一个字符就显示出来。当然你也可以考虑其他实现方式。这个C++的程序中,和C语言区别的主要是有些输入和输出不太一样。还有system("pause")这个是调用系统暂停功能,可能在TC等...

在C语言中,如何将一个浮点数变换成整数?
答:需要准备的材料分别有:电脑、C语言编译器。1、首先,打开C语言编译器,新建一个初始.cpp文件,例如:test.cpp。2、在test.cpp文件中,输入C语言代码:double a = 2.71828;printf("%d", int(a));。3、编译器运行test.cpp文件,此时成功将浮点数2.71828转换为了整数2。

在c语言中,如何从键盘输入一串包含数字和字母的字符串,以连续的数字构...
答:include<stdio.h>#include<string.h>#include<stdlib.h>#define INI20#define INC 10char* input;//指向动态数组int get_input();//用于接收输入值的函数,使用动态数组可以任意输入,无大小限制void ini();//系统初始化bool is_exit();//检测是否退出int split();//将字符串分解出6位的数字...

c语言一个结构体如何在多个源文件里面调用?
答:引用结构体有引用类型,和引用全局变量两种方式。1、引用类型。需要将结构体定义与头文件中(.h文件),然后在需要引用类型的源文件(.c)中,均引用该头文件,即可使用该类型。2、引用全局变量。要引用全局变量,需要先引用类型,之后在一个源文件中定义全局变量,在其它源文件中声明该全局变量,即可使用。