c语言函数指针DLL c语言函数指针交换两个数

c语言调用dll里的命令并输出

根据我的猜测,有两种情况

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册、网页空间、营销软件、网站建设、英山网站维护、网站推广。

1.如果 void GetNum(char* s);是把输入的字符储存在 *s中的话:

#include WINDOWS.H    

#include WINBASE.H

#include stdio.h    

typedef void (*MYPROC)(char*); /* 这里要与GetNum的返回值和参数 对应 */

void main(){

HINSTANCE LibHandle;

MYPROC ProcAdd; 

char ch;    

char sysbuf[] = "GetNum";   /*过程名*/

LibHandle = LoadLibrary("GetNum.dll"); /*载入dll*/ 

ProcAdd = (MYPROC)GetProcAddress(   

LibHandle, sysbuf);   /*获取函数sysbuf的地址*/

ProcAdd(ch);    

printf("%c\n",ch);

}

2.如果你的GetNum是

int GetNum(char* s)

{

int i=0,ans=0;

while(s[i]='0's[i]='9')

{

ans=s[i]-'0'+ans*10;

}

return ans;

}

#include WINDOWS.H    

#include WINBASE.H

#include stdio.h    

typedef int  (*MYPROC)(char*);           /*   改 */

void main(){

HINSTANCE LibHandle;

MYPROC ProcAdd; 

char s[100];                        /*   改 */

char sysbuf[] = "GetNum";   /*过程名*/

LibHandle = LoadLibrary("GetNum.dll"); /*载入dll*/ 

ProcAdd = (MYPROC)GetProcAddress(   

LibHandle, sysbuf);   /*获取函数sysbuf的地址*/

scanf("%s",s);                    /*   改 */

printf("%d\n", ProcAdd(s) );        /* 这里调用 并输出结果 */

}

c语言怎么调用dll文件

(1)编写程序时,你要包含(#include "什么.h") dll文件作者提供 的 头文件(.h文件) 。

程序里,便和普通函数调用一样,去调用它的函数。

(2)程序编译时,你要链接 dll文件作者提供 的 (.lib文件) 库文件。

当然,你可以在源程序里把.lib 名字 写上,编译时自动去链接,例子:

#pragma comment (lib, "什么.lib")

(3)执行时,要有 .dll 文件. 放在当前文件夹或系统文件夹里。

C#调用C++的dll中的函数,数组指针的问题

其实在.net开发中确实存在第三种类型——指针。但仅限于unsafe开发时使用!

对于dll调用问题,如果是pe格式的dll考虑使用PInvoke(平台调用)。而平台调用跟具体的unsafe开发是没有任何关联的,并不是说平台调用一定会用到非安全开发!由于.net本身隐藏了指针的使用,你不必要再去开辟任何指针了!所以这里显然是平台调用。

解答一个疑问:数组指针or指针数组?

数组指针指的一个指针,该指针指向一个数组。

指针数组是一个数组,一个数组里全是指针。

显然这使用是有区别,但这里并不涉及,在safe开发.net都不会涉及!

IntPtr是一种特殊的指针,这种针指的特殊性在于它向了设备!所以嘛,他也有一个名词——名柄,IntPtr多种在PInvoke时,传递设备句柄时使用(设备并不是硬件,有时一个文件也算是一个句柄的)。当然,这里也用不到!

现在说一下平台调用(PInvoke)中最重要的一个部分!数据封送!

也就是你写dll导入时应用使用的类型!

在C语言中声明与赋值分开写的时候多了去了!他生成文件时写一起与分开写并没有任何区别!所以分开写无所谓的!但是,多数时间你会发现,其实他分开写是为了你阅读的方便!为什么?因为声明时使用的类型是PUSHORT,而赋值时使用了USHORT的类型,这两句写在一块的话,很多人不会注意到赋值时使用的基础类型!所以分开写只是相当于想写一个注释而已!

平台对应的数据封送就在这里!USHORT在C/CPP中对就的一个byte!一定要注意,所以你知道的,他们使用的new USHORT[n]只是开辟了n个无符号数的字节!在.net平台封送时如何传递数据?当然用byte去接值,他是数组,你就用byte[]去接!

这里有一个问题你可能不知道,在.net中,最小的数是byte,而不是short和ushort!在.net中可以直接使用byte与其他数值进行运算!而short/ushort在.net中却是一个16bit数!占用两个字节!而C/Cpp为了确定类型,所以byte是byte,short/ushort是数值,但是short/ushort却是一个8bit数字!当然了,C/Cpp中的long才与.net中的int对应!

如果你明白这个,那么该用int[]还是该用short[]还是该用byte[]你自己就知道了!

第二个问题——你一直在想指针,其实你要传入的数组是地址而不是副本!换句话来说,在安全模式中我们是有ref/out修饰的!在dllImport时你传入byte[]是没有任何错误的!但是你能不能在从dll中将byte[]修改后的值带回就是两个字了!

一般情况下byte[]等数组本身就是引址的方式,所以不使用ref/out声明也是没有问题的!但是如果封装层在有一定的疑问存在时,最好还是声明成ref的方式较为合适。经常性的规律是,如果我们看到Cpp的header中说明是指针时,我们会使用ref声明,不是指针形式时可以不用ref/out声明,如果是**形式时,平台封送最好使用数组指针。这种情况并不多见!

但是,由于string类型也是引用形的,由于其特点,返回值一定要用ref/out(不管你看到Cpp的header中是什么类型),或者我们可以使用一个说明长度的byte[]也是可行的!

换句话来说,虽然我们可以说C#中的byte可以接short, short可以接int等等的对应关系!但其实在不改变内存字节长度的情况下,PInvoke对类型的要求并没有那么严格!比如你可以用string接收dll中传入的字符串,用byte[]也行的!用stringbuilder还行的!并没有严格上的限制!但是这里边一定要注意的是长度!换句话来说,对方使用的是USHORT[n],你用byte[n]能接回来。

是不是一定要有这个对应关系?不一定!

这种情况往往出来在自定类中。比如Cpp header中说明某个参数一个结构!这个结构是由一个short,一个字符串组成的!用C#时可以使用byte实现结构中对应的short,也可以用short实现对应的short,但在声明必须使用特定的长度说明,说明其只有一位!当然用,无论你用int还是long都可以,在结构中必须要说明长度只有一位!那个字符串也是一样!所以你完全可以看到,数据类型并不重要,平台封送中不用管具体的类型,要的只是长度!长度必须对应!

换句话来说,你用char[]来处理Cpp中的ushort也是可以的!

平台数据封送中重要一部分就是共长度(类型?开什么玩笑,Cpp不会认识.net中的类型的,当然.net也不会认识Cpp中的类型)。只有长度一致才能接到值!

cpp中肯定是哪种类型方便用哪种了,当然.net中也是哪种方便用哪种了!那么平台数据是如何进行传递的呢?答案就在于基本类型和结构!

基本类型不说了,当然是ushort只是一个byte,你用int无用谓!反正在.net中byte类型会自然转换成int。如果是ushort[],那么你必须是byte[]或char[]!你用int[]绝对会出现错误的!为了帮助理解,我这里说的是重点是结构:

假定一个结构有n个项(你可以理解为字段)组成。那么在数据封送时就是这n个项每一段的组合。经如有字段是USHORT类型,一个字段是Byte[10]类型,还有一个是Int类型,在平台封送时,我们要封装一段内存,长度为13,第一个长度为1表示第一字段,接下来10个表示第二字段,接下来2个表示 第三字段。

当然我们在.net方面也要构造一个对应的结构!第一个字段你可以声明成byte/short/int/long都可以(必须说明这个在内存中只有一个字节),如果你用了short却不说明,很显然你.net会接到前两字节,破坏了要接收的结构!你自己肯定拿不到数据的!

原理就这么多!慢慢看懂了就知道平台封送是怎么回事了!至于你的问题,抄个近路告诉你结果:dllImport声明时使用

static bool Read(short h, byte[] buffer, short n);

或者

static bool Read(short h, ref byte[] buffer, short n);

当然,也可以使用int,我并不反对

static bool Read([MarshalAs(UnManagerType.USHORT)] int h, byte[] buffer, short n);

换句话来说,你可以使用MarshalAsAttribute来指针其非托类型,结构时还可以直接使用长度说明。主要是你学会MarshalAsAttribute的使用,就知道参数如何传递了!

用C语言编写DLL

一.动态链接库(dll)结构

——dll中定义有两种函数:导出函数(export

function)和内部函数

(internal

function),导出函数可以被其他模块调用,内部函数只能在dll内部使用。我们在用c++定制dll文件时,需要编写的就是包含导出函数表的模块定义文件(.def)和实现导出函数功能的c++文件。下面以sample.dll为例介绍def文件和实现文件的结构:

——1.模块定义文件(.def)是由一个或者多个用于描述dll属性的模块语

句组成的文本文件,每个.def文件至少必须包含以下模块定义语句:

第一个语句必须是library语句,指出dll的名字。

exports语句列出被导出函数的名字。

可以使用description语句描述dll的用途(此句可选)。

";"对一行进行注释(可选)

——2.实现文件(.cpp文件为例)

——实现入口表函数的.cpp文件中,包含dll入口点处理的api函数和导出

函数的代码。

C语言如何调用DLL

//dll

#include windows.h

extern "C" //保持C语言文件

void _declspec ( dllexport ) tryProc()       //定义函数

{

MessageBox(NULL,_T("a"),_T("a"),MB_OK);

}

-------------------------------------

//C

#include windows.h

int main()

{

HMOUDLE dll = LoadLibrary(/*DLL文件名*/);

if(dll != NULL)

{

FARPROC try = GetProcAddress(dll,"tryProc");

if(try != NULL)

{

tryProc();//假如函数有返回值,可以用try()得到返回值

/*_asm call tryProc*/

}

}

return 0;

}


网站标题:c语言函数指针DLL c语言函数指针交换两个数
网页网址:http://ybzwz.com/article/hihcgd.html