欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C#调用非托管动态库中的函数方法

程序员文章站 2023-12-10 19:36:52
c#如何调用一个非托管动态库中的函数呢,比如用vc6写的动态库,总之c#调用动态库的过程是比java调用dll动态库方便快捷多了,下面举例说明这个过程。 1、创建一个非托...

c#如何调用一个非托管动态库中的函数呢,比如用vc6写的动态库,总之c#调用动态库的过程是比java调用dll动态库方便快捷多了,下面举例说明这个过程。

1、创建一个非托管动态库

代码如下:

复制代码 代码如下:

   //这一句是声明动态库输出一个可供外不调用的函数原型. 
   extern   "c"  __declspec(dllexport)  int  add( int ,  int ); 

   int  add( int  a, int  b)  
   { 
        //实现这个函数returna+b; 
   }


注意上面代码,一定要加上 extern"c" ,不能生成的动态库中的导出函数名就不会是add,而是像 ?add@@yahhh@z 样子,后面只是通过函数名 add 来定位函数入口就会出问题。

保存成c或者cpp文件都可以,接下来就用命令 cl (这个命令vc6提供) 来编译生成一个动态库,命令如下:

复制代码 代码如下:

c:\>cl /ld mylib.cpp
microsoft (r) 32-bit c/c++ optimizing compiler version 12.00.8804 for 80x86
copyright (c) microsoft corp 1984-1998. all rights reserved.

mylib.cpp
microsoft (r) incremental linker version 6.00.8447
copyright (c) microsoft corp 1992-1998. all rights reserved.

/out:mylib.dll
/dll
/implib:mylib.lib
mylib.obj
creating library mylib.lib and object mylib.exp


可以看到在c盘根目录下生成了你要的动态库 mylib.dll ,还伴随着生成了mylib.lib、mylib.obj、mylib.exp文件,上面命令cl的参数/ld就是生成动态库文件

2、编写c#程序调用动态库

复制代码 代码如下:

   using  system; 
   using  system.runtime.interopservices; //这是用到dllimport时候要引入的包 
   public   class  invokedll{ 

       [dllimport( "mylib.dll" , charset=charset.auto)] 
       staticexternint add( int  a, int  b); //声明外部的标准动态库, 跟win32api是一样. 

        public   static   void  main() 
       { 
         console.writeline(add(10,30)); 
       } 
   }


保存为invokedll.cs文件, 与mylib.dll置于同一目录, 编译该文件.
复制代码 代码如下:

c:\>csc invokedll.cs
microsoft (r) visual c# .net 编译器版本 7.10.3052.4
用于 microsoft (r) .net framework 版本 1.1.4322
版权所有 (c) microsoft corporation 2001-2002。保留所有权利。
将生成invokedll.exe, 可以执行该文件.

c:\>invokedll
40


我们看到c#调用了非托管动态库的函数 add 。执行前保证 mylib.dll 在能够被 invokedll 程序加载到的路径上。

回过头来,如果我们在mylib.cpp中没有加上 extern"c" 在,那么c中通过函数名 add 定位不到导出方法(因为函数名在动态库中已经变了),执行invokedll时就会出现如下错误。

复制代码 代码如下:

c:\>invokedll

未处理的异常: system.entrypointnotfoundexception: 无法在 dll mylib.dll 中找到名为 add 的入口点。
at invokedll.add(int32 a, int32 b)
at invokedll.main()


对于没有加上 extern "c" 的函数原型生成的动态库,我们就得用别的方式来调用了,具体怎么做,我现在还不知道。下面还有一个问题,上面的例子只是演示了动态库中函数非常简单的情况,如果函数传递的参数是指针,或者更复杂的数据类型,又如何操作呢?以后会深究的。

[注:]本文参考着网上一篇文章:c-sharp调用标准动态库 ,但是直接照着原文的操作就是会无法定位 add 的入口点的错误,所以略有修改。