关于如何在Windows上生成dll库

来源:互联网 发布:镇江淘宝模特兼职招聘 编辑:程序博客网 时间:2024/06/06 01:44

加上了自己的理解,和下面两位大神的作品,我也不知道自己是原创还是转载。仅是将自己的新的写出来,大家一起学习


鼓捣了一天半了,终于算是整明白了。

下面一一介绍流程,虽然网上已经有了好多教程,但是我这一版是针对在java环境下运行C++/C文件时,需要生成dll库时具体的操作。

里面所有的代码全部换成了我的代码

 

首先是这位大神的讲解

http://blog.sina.com.cn/s/blog_4a806bd9010007hn.html

 

JAVA以其跨平台的特性深受人们喜爱,而又正由于它的跨平台的目的,使得它和本地机器的各种内部联系变得很少,约束了它的功能。解决JAVA对本地操作的一种方法就是JNI。

 JAVA通过JNI调用本地方法,而本地方法是以库文件的形式存放的(在WINDOWS平台上是DLL文件形式,在UNIX机器上是SO文件形式)。通过调用本地的库文件的内部方法,使JAVA可以实现和本地机器的紧密联系,调用系统级的各接口方法。

简单介绍及应用如下:

一、JAVA中所需要做的工作

      在JAVA程序中,首先需要在类中声明所调用的库名称,如下:

static {

System.loadLibrary(“Test”);

}

在这里,库的扩展名字可以不用写出来,究竟是DLL还是SO,由系统自己判断。

还需要对将要调用的方法做本地声明,关键字为native。并且只需要声明,而不需要具体实现。如下:

public native static void set(int i);

public native static int get();

然后编译该JAVA程序文件,生成CLASS,再用JAVAH命令,JNI就会生成C/C++的头文件。

例如程序test.java,内容为:

public class test

{

    static

 {

  System.loadLibrary("Test");

 }

 public native static int get();

 public native static void set(int i);

 public static void main(String[]args)

 {


  test.set(10);

  System.out.println(test.get());

 }

}

 用javac test.java编译它,会生成test.class。再用javah test,则会在当前目录下生成testdll.h文件,这个文件需要被C/C++程序调用来生成所需的库文件。

由于是Android下的工程,因此.class文件已经自己自动生成了。如果是java文件需要到相应的路径下编译生成.class文件。

进入该路径D:\androidprogram\Testdll\bin\classes,javah com.example.testdll.**,想编译哪个就写哪个类的名字,蓝色下划线的是包名,不要和路径名混淆。

生成的头文件在D:\androidprogram\Testdll\bin\classes此路径下,

名为:com_example_testdll_test.h

二、C/C++中所需要做的工作

       对于已生成的.h头文件,C/C++所需要做的,就是把它的各个方法具体的实现。然后编译连接成库文件即可。再把库文件拷贝到JAVA程序的路径下面,就可以用JAVA调用C/C++所实现的功能了。

接上例子。我们先看一下com_example_testdll_test.h文件的内容:



/* DO NOT EDIT THIS FILE - it is machine generated*/

#include <jni.h>

/* Header for classcom_example_testdll_test */

 

#ifndef _Included_com_example_testdll_test

#define _Included_com_example_testdll_test

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:    com_example_testdll_test

 * Method:   set

 * Signature: (I)V

 */

JNIEXPORT void JNICALLJava_com_example_testdll_test_set

 (JNIEnv *, jclass, jint);

 

/*

 * Class:    com_example_testdll_test

 * Method:   get

 * Signature: ()I

 */

JNIEXPORT jint JNICALLJava_com_example_testdll_test_get

 (JNIEnv *, jclass);

 

#ifdef __cplusplus

}

#endif

#endif

在具体实现的时候,我们只关心两个函数原型

JNIEXPORT jint JNICALL Java_com_example_testdll_test_get(JNIEnv *, jclass);

和JNIEXPORT void JNICALL Java_com_example_testdll_test_set(JNIEnv*, jclass, jint);

       这里JNIEXPORT和JNICALL都是JNI的关键字,表示此函数是要被JNI调用的。而jint是以JNI为中介使JAVA的int类型与本地的int沟通的一种类型,我们可以视而不见,就当做int使用。函数的名称是JAVA_再加上java程序的package路径再加函数名组成的。参数中,我们也只需要关心在JAVA程序中存在的参数,至于JNIEnv*和jclass我们一般没有必要去碰它。

好,下面我们用Test.cpp文件具体实现这两个函数:

#include"com_example_testdll_test.h"

 

int i = 0;

int j;

JNIEXPORT jint JNICALLJava_com_example_testdll_test_get (JNIEnv *, jclass)

 

{

 

 return i;

 

}

JNIEXPORT void JNICALLJava_com_example_testdll_test_set (JNIEnv *, jclass, jint)

 

{

 

 i =j;

 

}

编译连接成库文件,本例是在WINDOWS下做的,生成的是DLL文件。并且名称要与JAVA中需要调用的一致,这里就是Test.dll

把Test.dll拷贝到testdll.class的目录下,java testdll运行它,就可以观察到结果了。

 

下面是针对红色画线的部分进行具体的讲解,来自于这个大神,但是该大神的还有与我的不同的地方,因此做了具体的修改,仅供大家参考

http://wenda.haosou.com/q/1374540952062422

用  vc  6.0  下的cl.exe  和  link.exe工具,请读下文:

声明:下面这篇文章不是我写的,源自:一个叫,有容乃大  的博客 

如何手工编写动态链接库(windows  dll)

 1.本例介绍在命令行(Console)环境下制作dll的方法

2.读者动手前,请确保在windows中安装有编译、链接工具和必要的函数库文件。

 3.本例使用C语言实现.

 4.本例中使用路径均为我机器上的绝对路径,读者需根据实际情况调整。

工具要求:

Microsoft的编译器cl.exe 

MIcrosoft链接器link.exe

dll制作步骤:

1.编写dll函数实现源代码Test.cpp(该cpp在上个大神的文章里已经写完了)

2.编写dll函数输出定义文件Test.def.

 

LIBRARY Test

EXPORTS

Java_com_example_testdll_test_get @1

Java_com_example_testdll_test_set @2

 

3.编译dll源码,生成dll,lib文件.

 

3.1  新建命令行窗口

3.2  设置PATH  ¦ INCLUDE  ¦  LIB  3个环境变量.

 

SET Path= D:\VS2010setup\VC\bin;%Path%

SET INCLUDE= D:\VS2010setup\VC\include;%INCLUDE%

SET LIB= D:\VS2010setup\VC\lib;%LIB%

 

//这里是为了防止出现cannot find kernel32.lib的错误

在系统的环境变量中:要新建一个名称为LIB和INCLUDE的环境变量,以对应上文中的由紫色标记处的部分。

LIBC:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib;//不用更改

C:/ProgramFiles/Microsoft SDKs/Windows/v5.0/Lib;//不用更改

D:\VS2010setup\VC\lib//自己电脑上VClib库路径

3.3  编译Test.cpp

 

cd  D:\androidprogram\Testdll\jni  (hello.c和hello.def所在目录)

cl /c  Test.cpp

这里会出现不能找到jni.h文件,解决办法是

 

将一下路径中的文件

\jdk\include\jni.h    

\jdk\include\win32\jawt_md.h   

\jdk\include\win32\jni_md.h  
复制到Visual Studio的安装目录下的\VC\include目录中

 

3.4  链接Test.obj,生成Test.dll, Test.lib两个文件.

 

link /def:Test.def  /dll  Test.obj

这里就会出现两个错误,

1 找不到kernel32.dll文件,解决办法已经给出

2 extra operand “Test.obj”我出现这个错误的原因主要是在于点击这里没有弄好

 

至此,我的库文件就弄好了。

 

4.测试dll函数.

 

4.1  编写测试代码  test.c

 

extern int  say_hello(char*  name);

int main(int  argc,char**  argv)

{

say_hello( "robbie ");

return 0;

}

 

4.2  编译测试代码test.c

 

cl /c  test.c

 

4.3  链接test.obj和  hello.lib,生成可执行文件test.exe

 

link test.obj  hello.lib

 

4.4  运行test.exe,屏幕输出:

 

hello robbie

 

至此,一个dll构造完毕.

 

 

下面是我自己的一点补充:

     如果要在c++下,或者win32    mfc下使用标准c写的dll,必须把上面的声明

extern int  say_hello(char*  name);改成:extern  "C "  int say_hello(char*  name);

0 0