首页 > 开发 > 综合 > 正文

关于C#中的DLLImport

2024-07-21 02:28:30
字体:
来源:转载
供稿:网友
国内最大的酷站演示中心!

msdn中对dllimportattribute的解释是这样的:可将该属性应用于方法。dllimportattribute 属性提供对从非托管 dll 导出的函数进行调用所必需的信息。作为最低要求,必须提供包含入口点的 dll 的名称。

并给了一个示例:

[dllimport("kernel32.dll", entrypoint="movefilew",  setlasterror=true,

charset=charset.unicode, exactspelling=true,

callingconvention=callingconvention.stdcall)]

public static extern bool movefile(string src, string dst);

上网搜了一下,最常见的就是使用它来调用win32的api,例如上面所示。或者调用一下c或c++编写的dll。

这东西没怎么用过。只是前几天忽然分配下一个临时的任务,做一个“停车厂管理”的小东西,听说是一个大干部的小孩子要弄这么个东西,那干部是公司的客户,讨论正经事之余又拜托了我们做这么个小东西。其中用到了单片机模拟车辆出入的一些信号。

我对单片机一窍不通,好在有人写好了轮询单片机的dll,我只管调用,由于是c++写的,于是将dll拷贝到bin目录后(这dllimport会从程序启动目录开始查找相应名称的dll,未找到则转至system32下查找),用dllimport来调用,但在这个过程中遇到了几个问题:

1.看了一下c++的代码,需要用到的只有三个方法:

bool openserialport1()

bool fngetio(unsigned char& p1, unsigned char& p2, unsigned char& p3)

bool closeserialport1()

于是就在自己的程序中写了:

using system.runtime.interopservices;

……

[dllimport("getiodll.dll", entrypoint = "openserialport1")]

public static extern bool openserialport1();

[dllimport("getiodll.dll", entrypoint = "fngetio")]

public static extern bool fngetio(ref byte p1, ref byte p2, ref byte p3);

[dllimport("getiodll.dll", entrypoint = "closeserialport1")]

public static extern bool closeserialport1();

然而程序在运行时无论如何总是提示“找不到入口点”,搞得懵了,只好上网搜去,最后下了一个叫exescope的小软件,装完之后查看该dll,果然如贴子中写的,dll中的函数名称发生了变化,分别成了:

[email protected]@ya_nxz

[email protected]@[email protected]

[email protected]@ya_nxz

将这些怪怪的名称代入到entrypoin中,编译运行,没有问题了。

2.可是接上单片机之后,问题又来了,虽然openserialport1返回的结果是true,但fngetio读出一数据全是0,按理应该是全1才对。来了一个同事,说反正有源码,把原来的dll弄成标准c的试试,标准c不标准c的我也没明白,让那人给改了一下,把编译之后的dll拷到自己程序的bin下,将entrypoin换成正常的函数名,运行,这回是真的ok了。

读写.ini文件时,也会用到dllimport,不过现在.ini文件好像用得少了,下面是读写的程序:

{

publicstring path;

[dllimport("kernel32")]

privatestaticexternlong writeprivateprofilestring(string section,string key,string val,string filepath);

[dllimport("kernel32")]

privatestaticexternint getprivateprofilestring(string section,string key,string def,stringbuilder

retval,int size,string filepath);

public inifile(string inipath)

{

       path = inipath;

}

publicvoid iniwritevalue(string section,string key,string value)

{

       writeprivateprofilestring(section,key,value,this.path);

}

publicstring inireadvalue(string section,string key)

{

       stringbuilder temp = new stringbuilder(255);

       int i = getprivateprofilestring(section,key,"",temp,255,this.path);

       return temp.tostring();

}

}

网上关于dllimport的很多问题是由于所调方法的参数比较复杂,现在我还没用到,看到一篇贴子,参数中带指针的,也先录下来,以备将来查用:

参数是用指针来获取一个数组:int getdata(byte * pbuffer)  

pbuffer是数组的首地址,也就是说getdata会写pbuffer[0],pbuffer[1]....pbuffer[100];

答曰:

[dllimport("yourdllfile.dll"]  

private static extern int getvalue([marshalas(unmanagedtype.lparray)]byte[] pvalue);

如果是out参数,可以如下  

[dllimport("yourdllfile.dll")]  

private static extern int getvalue([out,marshalas(unmanagedtype.lparray)]byte[] pvalue);

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表