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
中的函数名称发生了变化
,
分别成了:
?OpenSerialPort1@@YA_NXZ
?fnGetIO@@YA_NAAE00@Z
?CloseSerialPort1@@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);
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1438350