㈠ error C2485: 'align' : unrecognized extended
vc是沒有align這種對齊用法的,只有intel c++ compile 才能編譯通過.
用#pragma pack(n)基本是一樣的,而且是微軟的東西
㈡ 用C語言編寫DLL
使用微軟的vc或者vs,用c語言編程就是了。創建工程的時候會問你是創建什麼樣的工程,比如控制台程序,mfc程序,動態庫(dll)等。
c和c++只是編程語言,動態庫依賴於操作系統,在哪個平台下就依賴於哪個平台的動態庫生成工具。linux下是so文件,用gcc編譯器就可以生成。
㈢ java 如何調用一個已經存在的靜態庫,並輸入和獲取參數! 例如:靜態庫中已經存在函數 ret=ys_tpcall(aa);
給出一個windows下dll的實例。linux下.a的靜態庫只是頭文件和編譯有所不同,另外需要將編譯後的動態庫文件放入/usr/lib下,使用ldconfig載入。
一 先製作一個系統中有的DLL文件(cpp給出的sdk介面)
既然是測試我們就把我們這個dll叫做testDll吧,為了簡單其間,我只寫一個add方法,就是簡單的2個數字相加,對於真正的開發中我們肯定會遇到其他類型,java到c/cpp中類型需要轉換,具體類型轉換對應關系g一下就能得到,我也不在列舉。c/cpp中一個class一般包含2個文件,一個頭文件定義(*.h),一個文件主體(*.c/*.cpp)。啰嗦了這么多還是直接動手吧,先在vs2008中建立一個工程(當然你也可以直接編寫不用這些IDE工具,gcc g++的命令自己g。下同,不在注釋不在廢話),選取win32工程
鍵入工程名字testDll,點擊next選取DLL,然後點擊完成
打開我們的testdll.cpp,添加進我們的add方法
C++代碼
1.int add(int a,int b){
2. return a+b;
3.}
int add(int a,int b){
return a+b;
}
注意到文件列表裡並沒有testDll.h,因為我們要給出調用者一個介面,如果不給頭文件,人家就沒辦法調用,所以我們就必須添加一個頭文件testDll.h。
C++代碼
1.#ifdef TEST_DLL
2.#define TEST_API __declspec(dllexport)
3.#else
4.#define TEST_API __declspec(dllimport)
5.#endif
6.
7./* Set up for C function definitions, even when using C++ */
8.#ifdef __cplusplus
9.extern "C" {
10.#endif
11.
12.TEST_API int add(int,int);
13.
14./* Ends C function definitions when using C++ */
15.#ifdef __cplusplus
16.}
17.#endif
#ifdef TEST_DLL
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
extern "C" {
#endif
TEST_API int add(int,int);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
#endif
在這個頭文件中我們把我們的add方法給定義了進去。注意到testdll.cpp中#include "stdafx.h",所以我們就把這個testDll.h include進stdafx.h裡面。
按道理說我們的這個dll已經完成了,但是一般c/cpp給介面SDK的時候大都給.h和.lib,為了一步生成dll和lib,我們添加進一個testDll.def,有了這個文件就可以一步生成dll和lib。在source file里右鍵add new item ,選擇Mole-Definition File
鍵入testDll,OK了,我們可以直接build了。生成testDll.dll和testDll.lib。
把testDll.dll扔到system32目錄里等待我們高大威猛的java jni調用。
二 JNI
2.1 編寫java文件
為了顯示我們的與眾相同,我們就把我們的這個java文件命名為Demo.java順便直接帶上包名
,因為我們知道人家給我們的介面里有個add方法,所以我們就直接來個調用吧。
Java代碼
1.package com.testJni.testDemo;
2.
3.public class Demo {
4. static
5. {
6. //System.out.println(System.getProperty("java.library.path"));
7. System.loadLibrary("testDll");
8. System.loadLibrary("jniDll");
9. }
10. public native static int add(int a,int b);
11.
12.}
package com.testJni.testDemo;
public class Demo {
static
{
//System.out.println(System.getProperty("java.library.path"));
System.loadLibrary("testDll");
System.loadLibrary("jniDll");
}
public native static int add(int a,int b);
}
demo.java代碼暫時如此,我們把將要生成的jni的dll叫做jniDll,有童鞋講,我不想用你這個爛名字jniDll多俗啊,沒關系,你可以換,隨你換,生成文件後你再換也可以,現在換也可以。
2.2 生成.h頭文件
javah命令,不多講。生成的文件com_testJni_testDemo_Demo.h這個文件的命名規則我就不多講了,一目瞭然。
C++代碼
1./* DO NOT EDIT THIS FILE - it is machine generated */
2.#include <jni.h>
3./* Header for class com_testJni_testDemo_Demo */
4.
5.#ifndef _Included_com_testJni_testDemo_Demo
6.#define _Included_com_testJni_testDemo_Demo
7.#ifdef __cplusplus
8.extern "C" {
9.#endif
10./*
11. * Class: com_testJni_testDemo_Demo
12. * Method: add
13. * Signature: (II)I
14. */
15.JNIEXPORT jint JNICALL Java_com_testJni_testDemo_Demo_add
16. (JNIEnv *, jclass, jint, jint);
17.
18.#ifdef __cplusplus
19.}
20.#endif
21.#endif
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_testJni_testDemo_Demo */
#ifndef _Included_com_testJni_testDemo_Demo
#define _Included_com_testJni_testDemo_Demo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_testJni_testDemo_Demo
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_testJni_testDemo_Demo_add
(JNIEnv *, jclass, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
2.3 用c/cpp實現這個頭文件
c/cpp中已經實現了這個add方法,我們只需要調用就可以啦。所以直接vs2008中建立一個dll工程,工程名我們就叫jniDll,具體過程不再多講,方法同上面testDll的建立一樣。在這個工程里kimmking把需要引用的包、文件等已經講的很清楚了。打開jniDll.cpp,添加下面代碼
C++代碼
1.JNIEXPORT jint JNICALL Java_com_testJni_testDemo_Demo_add
2.(JNIEnv *env,jclass jobject,jint a,jint b){
3.
4. return add(a,b);
5.}
JNIEXPORT jint JNICALL Java_com_testJni_testDemo_Demo_add
(JNIEnv *env,jclass jobject,jint a,jint b){
return add(a,b);
}因為int對應的類型就剛好是jint,所以就不需要轉換,其他需要轉換的類型自己g對應關系轉換,注意釋放。
這個工程里我們還需要打開 stdafx.h添加
C++代碼
1.#include <jni.h>
2.
3.#include "testDll.h"
4.#include "com_testJni_testDemo_Demo.h"
#include <jni.h>
#include "testDll.h"
#include "com_testJni_testDemo_Demo.h"
在編譯這個jniDll工程的時候需要引入testDll.h,com_testJni_testDemo_Demo.h,另外添加testDll.lib這個依賴。
好了做好這些後,build下,生成了我們期待已久的jniDll.dll,把這個dll同樣扔到system32下。
三 測試
本人特懶,不想寫多餘的class,所以直接修改Demo.java 這也是剛才為什麼講暫時如此的原因
Java代碼
1.package com.testJni.testDemo;
2.
3.public class Demo {
4. static
5. {
6. //System.out.println(System.getProperty("java.library.path"));
7. System.loadLibrary("testDll");
8. System.loadLibrary("jniDll");
9. }
10. public native static int add(int a,int b);
11. public static void main(String[] args) {
12. System.out.println(add(7,2));
13. }
14.}
package com.testJni.testDemo;
public class Demo {
static
{
//System.out.println(System.getProperty("java.library.path"));
System.loadLibrary("testDll");
System.loadLibrary("jniDll");
}
public native static int add(int a,int b);
public static void main(String[] args) {
System.out.println(add(7,2));
}
}
四 最後補充
如果系統已經載入過c/cpp的dll,我們就不用再System.loadLibrary("testDll")了,載入一遍就可以了,因為我們剛才寫的testDll系統沒有載入,所以我就載入了一下。對於多個dll可以寫多個System.loadLibrary去載入,修改static{}裡面的內容不需要重新生成dll,除非你多加了一個調用方法,如果你看清楚規則,就不用javah命令就可以直接編寫頭文件,用javah太麻煩了。