精华内容
下载资源
问答
  • 跨平台调用之一——java调用so

    千次阅读 2019-11-10 20:37:31
    之前已经试过用c调用.a库,也有总结在工作文档中,下面在家试试用java调用.so库(其实很相似) 建立项目: 1.编写源文件: package com.demo.TestLib.JniSo; public class Hello{ static{ System.load("/lib/...

    之前已经试过用c调用.a库,也有总结在工作文档中,下面在家试试用java利用jni(jna应该更方便)调用.so库(其实很相似,不过之前是Linux,这里是win)
    建立项目:
    在这里插入图片描述
    1.编写源文件:

    package com.demo.TestLib.JniSo;
    
    public class Hello{
    	static{
    		System.load("/lib/libHello.so");
    	}
    	public native void say();
    	
    	public native String world(String str);
    	
    	public static void main(String...args){
    	Hello hello = new Hello();
    	hello.say();
    	System.out.println("java : "+hello.world("hello"));
    	}
    }
    
    

    2.编译Hello.java - Hello.class
    在这里插入图片描述
    解决办法:将系统变量中的path路径,也复制到用户变量的Path路径中,(为什么呢?)
    在这里插入图片描述
    在这里插入图片描述
    3.编译Hello.class 生成 com_jni_Hello.h 的头文件
    资料中说:用
    在这里插入图片描述
    但是jdk9之后(大概)javah不可用了,应:
    在这里插入图片描述
    生产了一个头文件:
    在这里插入图片描述
    4.编写c++/c的业务代码,引用com_jni_Hello.h 的头文件,并实现定义的方法

    #include "com_demo_TestLib_JniSo_Hello.h"
    #include "string.h"
    JNIEXPORT void JNICALL Java_com_demo_TestLib_JniSo_Hello_say(JNIEnv *env, jobject object){
     
            printf("hello world!");
      }
    
    JNIEXPORT jstring JNICALL Java_com_demo_TestLib_JniSo_Hello_world(JNIEnv *env, jobject obejct, jstring string){
              const char *wd = " world!!";
              const char *getstr = (*env)->GetStringUTFChars(env,string, 0);
              char *str;
    
              str=strcpy(str,wd);
              str=strcpy(str,getstr); 
    
             jstring out= (*env)->NewStringUTF(env,str);
    
              return out;
      }
    
    

    以下待完成:

    5.编译c/c++ 代码生成动态链接库 .so文件

    gcc -fPIC -D_REENTRANT C:\java\jdk-13\include\win32 -c Hello.c
    

    在这里插入图片描述


    6:把so的路劲添加到LD_LIBRARY_PATH变量

    export LD_LIBRARY_PATH=/home/admin/lib

    7: 运行java程序

    java com.jni.Hello
    
    8:结果
    
    java : hello
    hello world!
    

    ————————————————
    版权声明:本文为CSDN博主「ailice001」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/ailice001/article/details/79880876

    另:
    1.so为linux下的产物,所以我用windows没有道理。。。。再讨论吧
    so库文件使用
    2.java调用dll倒是需要学习
    java调用dll库
    3.java利用jna调用.so库
    添加链接描述

    展开全文
  • Android调用so库, so库是c语言编写, 在linux 64位系统+ndk(32位)生成 lib*.so (32位) 环境: 操作系统:Redhat Server 63 编译软件:Code::blocks 开发库:android-ndk-r9c-linux-x86.tar.bz2 2) Android客户端...

    Android调用so库, so库是c语言编写, 在linux 64位系统+ndk(32位)生成 lib*.so (32位)

    1. 所需软件环境:

    1)so库开发环境

    操作系统: Redhat Server 6.3  x86_64

    编译软件:Code::Blocks

    Android native开发库:android-ndk-r9c-linux-x86.tar.bz2 

    [xxx@www ~]$ uname -a
    Linux www.teleframe.cn 2.6.32-279.el6.x86_64 #1 SMP Wed Jun 13 18:24:36 EDT 2012 x86_64 x86_64 x86_64 GNU/Linux
    [xxx@www ~]$ cat /proc/version
    Linux version 2.6.32-279.el6.x86_64 (mockbuild@x86-008.build.bos.redhat.com) (gcc version 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC) ) #1 SMP Wed Jun 13 18:24:36 EDT 2012
    [xxx@www ~]$ cat /etc/issue
    Red Hat Enterprise Linux Server release 6.3 (Santiago)
    Kernel \r on an \m

    2) Android客户端开发

    操作系统:Windows 7 x86

    测试环境: Android手机(系统4.0及以上)

    开发工具和SDK包: adt-bundle-windows-x86-20131030.zip(里面含有Eclipse)

    本文所需软件如下:

    2. 环境搭建

    1)Code::Blocks环境搭建

          首先安装Code::Blocks, 然后解压 android-ndk-r9c-linux-x86.tar.bz2 , 如解压到桌面  /home/UserName/Desktop/android-ndk-r9c/
          然后启动Code::Blocks,  进行系统环境配置

         1.1) 配置全局环境

               S1:  打开  Settings-> Compiler and debugger... 

               S2:  选择编译器Selected complier ->  GNU ARM GCC Complier,或自己新建一个

               S3:  选择 Toolchain executables

               S4:  设置android-ndk路径( Complier's installation directory ) ,如 /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86

               S5:  设置Program Files各个编译程序

                      C complier:                       arm-linux-androideabi-gcc

                      C++ compiler:                  arm-linux-androideabi-g++

                      Linker for dynamic libs:  arm-linux-androideabi-g++

                      Linker for static libs:        arm-linux-androideabi-ar

                      Debugger:                         arm-linux-androideabi-gdb

                      Resource compiler:        

                     

               S6: 设置Additional Paths,  增加(Add)  :  /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/arm-linux-androideabi/bin

               S7: 设置 Search directories -> Compiler,  增加(Add)  : /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/include

               S8: 设置 Search directories -> Linker,

    /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib
    /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6
    /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/lib/gcc/arm-linux-androideabi/4.6/armv7-a

                  

               S9:  设置完成,点击确定

        1.2) 配置项目的环境

             S1:  右击项目,选择Build options,  Selected Complier选择刚才设置的那个  GUN ARM GCC Compiler 

             S2:  Compler settings -> Other options , 写入  -fPIC

             S3:  设置 Search directories -> Linker,  Add : 

    /home/xxx/Desktop/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib

            S4: Search directories->Complier , Add

    /home/xxx/Desktop/android-ndk-r9c/platforms/android-14/arch-arm/usr/include

    2)Android 开发环境搭建

         直接解压 adt-bundle-windows-x86-20131030.zip , 如解压到  E:\Program Files\adt\adt-bundle-windows-x86-20131030 

         

         就可以看到里面以及放好了eclipse, 此处的eclipse默认已经配置好了 adt,  启动 eclipse.exe 配置android虚拟机

        菜单 Window -> Android Virtual Device Manager  管理虚拟机, Android SDK Manager 可以更新 SDK,由于此adt所带android系统是4.4,  建议再 更新 4.0.3 (

               手动更新详见: 手动下载Android开发SDK
                     sdk:platform -> https://dl-ssl.google.com/android/repository/android-14_r03.zip
                     sdk:system-image -> https://dl-ssl.google.com/android/repository/sysimg_armv7a-14_r02.zip 
         )

        如下图所示

        

        新建一个虚拟机

        

    3. SO库编写

        3.1)生成头文件

            打开adt-bundle-windows里面的Eclipse

            新建Android项目JniTestAndroid ,建立包 com.lpr, 建类  JniTestAndroid

            JniTestAndroid.java

    package com.lpr;
    class JniTestAndroid {
        public native byte[]  recognition(byte arr[]);
          static {
    	System.loadLibrary("AndroidCallsoDemo");//Load  AndroidCallsoDemo.so produce by code::blocks
        //  System.out.println(System.getProperty("java.library.path"));
        //  System.setProperty("java.library.path", ".");
          }
    }
    

     用 Javac 编译成 class文件
    >cd E:\JniTestAndroid
    >javac com/lpr/JniTestAndroid.java
    >javah com.lpr.JniTestAndroid
    
    现在生成了  com_lpr_JniTestAndroid.h
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_lpr_JniTestAndroid */
    
    #ifndef _Included_com_lpr_JniTestAndroid
    #define _Included_com_lpr_JniTestAndroid
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_lpr_JniTestAndroid
     * Method:    recognition
     * Signature: ([S)[B
     */
    JNIEXPORT jbyteArray JNICALL Java_com_lpr_JniTestAndroid_recognition
      (JNIEnv *, jobject, jbyteArray);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    现在将com_lpr_JniTestAndroid.h拷贝到 Redhat 下面

    并将 $java_home/include/jni.h 和 ./linux/jni_md.h 拷贝到 redhat 下面

    在此特给出 jni_md.h 源码

    #ifndef _JAVASOFT_JNI_MD_H_
    #define _JAVASOFT_JNI_MD_H_
    
    #define JNIEXPORT
    #define JNIIMPORT
    #define JNICALL 
    
    typedef long jint;
    typedef __int64 jlong;
    typedef signed char jbyte;
    
    #endif /* !_JAVASOFT_JNI_MD_H_ */
    

          3.2)编写SO库

                 打开Code::Block新建(动态库)项目 AndroidCallsoDemo, 设置项目属性  参考上面的【 1.2  配置项目的环境】

                 添加 com_lpr_JniTestAndroid.h, jni.h,  jni_md.h 到项目(不添加也可以,只要放到项目的更目录即可)

                main.cpp

    #include "stdio.h"
    #include "com_lpr_JniTestAndroid.h"
    
    JNIEXPORT jbyteArray JNICALL Java_com_lpr_JniTestAndroid_recognition
    (JNIEnv *jnienv, jobject jobj, jbyteArray byteArray)
    {
        /*    short*  iArray ; //=new short[maxSize];
            jboolean jbool = true;
            //转换数组
            iArray = jnienv->GetShortArrayElements(shortArray, &jbool);
            //...
            //
            jnienv->ReleaseShortArrayElements(shortArray,iArray,0);
            // do something with iArray ...
    
    
            // carnumber;
        */
        char carnumber[64]= {"你输入的是:"};
    
        jbyteArray  returnLPRArray = jnienv->NewByteArray( 64 );
        jbyte *retbytes = jnienv->GetByteArrayElements( returnLPRArray, 0);
    
        jbyte *bytes2 = jnienv->GetByteArrayElements(byteArray, 0);
    
        sprintf(carnumber, "%s %s",carnumber, bytes2);
    
        int nLPRLen = strlen(carnumber);
        //返回值最好是 byte,以免utf8造成汉字的影响
        for ( int i = 0; i < nLPRLen;  i++ )
        {
            retbytes[ i ] = carnumber[ i ];
        }
    
        jnienv->SetByteArrayRegion(returnLPRArray, 0, nLPRLen, retbytes );
    
        return   returnLPRArray ;
    }

                

               几点注意:

                1. 如果传入参数或传出参数有汉字或比较复杂的结构,建议都化为 jbyteArray, 特别是有关的汉字问题


    4. Android编写

      建立android项目 JniTestAndroid

      activity_karl.xml // 

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#F5F6F2"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".KarlActivity" >
    
        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:text="result"
            android:textSize="20sp" />
    
    
        <Button
            android:id="@+id/button1"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_below="@+id/textView"
            android:gravity="center_horizontal"
            android:text="Button" />
    
    </RelativeLayout>

     拷贝  com.lpr.JniTestAndroid  到项目 src 下面

    karlActivity.java

    package com.karl.jnitestandroid;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.TextView;
    
    import com.lpr.JniTestAndroid;
    
    public class KarlActivity extends Activity {
    
    	private JniTestAndroid jni = new JniTestAndroid();
    	private Button bt;
    	private TextView textView;
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_karl);
    		
    		textView = (TextView)findViewById(R.id.textView);  
    		bt = (Button) findViewById(R.id.button1);  
    		bt.setOnClickListener(new OnClickListener(){
    
    			@Override
    			public void onClick(View arg0) {
    				String str="中国北京123ABC";
    				byte data[] =  jni.recognition(str.getBytes());
    				String text = new String(data); //new String(data, "GB2312");
    				textView.setText(text);
    			}
    		});
    	}
    
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		// Inflate the menu; this adds items to the action bar if it is present.
    		getMenuInflater().inflate(R.menu.karl, menu);
    		return true;
    	}
    
    }
    

    运行结果


    5.  常见错误

      5.1)  ld: error: cannot open crtbegin_so.o: No such file or directory

    arm-linux-androideabi-g++ -Wall -fexceptions  -O2 -fPIC    -I../android-ndk-r9c/platforms/android-14/arch-arm/usr/include  -c main.cpp -o obj/Release/main.o
    /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/as: /lib/libz.so.1: no version information available (required by /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/as)
    arm-linux-androideabi-g++ -shared -L../android-ndk-r9c/platforms/android-14/arch-arm/usr/lib -L/home/haifeng/android/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib  obj/Release/main.o   -o bin/Release/libAndroidCallsoDemo.so -s  
    /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtbegin_so.o: No such file or directory
    /home/haifeng/android/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: error: cannot open crtend_so.o: No such file or directory
    collect2: ld returned 1 exit status

    原因是ld找不到  crtbegin_so.o 和 crteng_so.o, 解决方法是,在项目源码下面建立软连接

    cd /home/xxx/android/AndroidCallsoDemo/
    ln -s /home/xxx/android/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib/crtend_so.o ./
    ln -s /home/xxx/android/android-ndk-r9c/platforms/android-14/arch-arm/usr/lib/crtbegin_so.o ./

        5.2) 查看SO库的依赖库

            查看PC linux  平台是用 ldd,  查看嵌入式的用  arm-linx-*-readelf

    /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-readelf -a AndroidCallsoDemo.so
    或者
    /home/xxx/Desktop/android-ndk-r9c/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-readelf -a AndroidCallsoDemo.so | grep "Shared"

       5.3) 使用STL
       直接使用STL或用Opencv间接调用STL, 提示找不到  #include <algorithm> 等,  在工程的 Build Options ->  Search directories -> Complier添加如下包含目录即可
    /home/xxx/Desktop/android-ndk-r9c/sources/cxx-stl/gnu-libstdc++/4.6/include
    /home/xxx/Desktop/android-ndk-r9c/sources/cxx-stl/gnu-libstdc++/4.6/libs/armeabi-v7a/include

    点此处下载源码

    QQ: 1505974441

    [2014.2.18 14:26:00]


    展开全文
  • 单个.c文件生成.so: cd /d D:\Program Files (x86)\MinGW\bin gcc "D:\VisulStudio\gccSPA\gccSPA\SolarPosAngle.c" -fPIC -shared -o "D:\VisulStudio\gccSPA\gccSPA\gccSPA.so" python中调用...
    单个.c文件生成.so:
    cd /d D:\Program Files (x86)\MinGW\bin
    gcc "D:\VisulStudio\gccSPA\gccSPA\SolarPosAngle.c" -fPIC -shared -o "D:\VisulStudio\gccSPA\gccSPA\gccSPA.so"
    python中调用
    from ctypes import *
    aimHandle = CDLL("D:\VisulStudio\gccSPA\gccSPA\gccSPA.so")
    aimHandle.main1.restype = c_double
    aimHandle.main2.restype = c_double
    aimHandle.main3.restype = c_double
    aimHandle.main3.argtypes = (c_int, c_int, c_int, c_int, c_int, c_double, c_double)
    
    SZA = aimHandle.main1()
    SAA = aimHandle.main2()
    print "1.SZA, SAA:",SZA, SAA
    
    second_c = int(second)
    second_c = c_int(second_c)
    lat_c = c_double(lat)
    lon_c = c_double(lon)
    SZA = aimHandle.main3(year,dayNum,hour,minute,second_c,lat_c,lon_c)

    一定要有函数输入输出类型的声明,int型不用转换,float和double类型需要进行转换,多个变量输入单个变量输出。

    python位数要统一。如果出现win32,建议将python卸载,然后重新安装python和相应的库。

    126的问题需要重新编译.so文件。

     

     

    展开全文
  • java通过 JNA调用 so

    万次阅读 2015-11-28 10:56:34
    Win32 程序。 选择 dll 类型。   2 ,发布的 C 函数是:   #define MYLIBAPI   extern   "C"   __declspec ( dllexport )     MYLIBAPI void say( wchar_t * pValue); ...
    
    JNA—JNI终结者

     

    介绍

    给大家介绍一个最新的访问本机代码的Java框架—JNA

    JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。

    JNA项目地址:https://jna.dev.java.net/

     

    非常强大、易用,功能上类似与.NETP/Invoke

     

     

     

    不堪回首的JNI

    我们知道,使用JNI调用.dll/.so共享类库是非常非常麻烦和痛苦的。

    如果有一个现有的.dll/.so文件,如果使用JNI技术调用,我们首先需要另外使用C语言写一个.dll/.so共享库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的  dll/so中公布的函数。

    然后再在Java中载入这个适配器dll/so,再编写Java   native函数作为dll中函数的代理。

    经过2个繁琐的步骤才能在Java中调用本地代码。

    因此,很少有Java程序员愿意编写调用dll/.so库中的原生函数的java程序。这也使Java语言在客户端上乏善可陈。可以说JNIJava的一大弱点!

     

    .NET平台上强大的P/Invoke

    而在.NET平台上,强大的P/Invoke技术使我们Java程序员非常羡慕。使用P/Invoke技术,只需要使用编写一个.NET函数,再加上一个声明的标注,就可以直接调用dll中的函数。

    不需要你再使用C语言编写dll来适配。

     

     

    不逊于P/InvokeJNA

    现在,不需要再羡慕.NETP/Invoke机制了。JNA把对dll/.so共享库的调用减少到了和P/Invoke相同的程度。

     

    使用JNA,不需要再编写适配用的.dll/.so,只需要在Java中编写一个接口和一些代码,作为.dll/.so的代理,就可以在Java程序中调用dll/so

     

     

    JNA快速启动

     

         现在让我们直接进入JNA的世界。

     

    你只需要下载一个jar包,就可以使用JNA的强大功能方便地调用动态链接库中的C函数。

    1,下载jna.jar

    在这里https://jna.dev.java.net/servlets/ProjectDocumentList?folderID=7408&expandFolder=7408&folderID=0

     

     

    2,现在你已经可以使用JNA了。

    为了方便你参考JNAjava类库,我制作了《JNA3.09API参考手册》,是CHM格式的。你可以到这里下载 http://download.csdn.net/source/900438

     

     

     

     

    JNA例子

     

    例子1   

    现在让我们运行一个JNA程序,感受它的强大威力。

    1,在Java项目中引入jna.jar包。

    2,创建一个类:

     

    import com.sun.jna.Library;

    import com.sun.jna.Native;

    import com.sun.jna.Platform;

     

    /** Simple example of native library declaration and usage. */

    public class HelloWorld {

     

        public interface CLibrary extends Library {

            CLibrary INSTANCE = (CLibrary)

                Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),

                                   CLibrary.class);

       

            void printf(String format, Object... args);

        }

     

        public static void main(String[] args) {

            CLibrary.INSTANCE.printf("Hello, World/n");

            for (int i=0;i < args.length;i++) {

                CLibrary.INSTANCE.printf("Argument %d: %s/n", i, args[i]);

            }

        }

    }

     

     

     

     

    3,执行,可以看到控制台中打印出了

    Hello, World

     

        但是,请注意,这个程序实际上是使用msvcrt.dll这个C运行时库中的printf函数打印出上面这些字符的。

     

        看,多简单,不需要写一行C代码,就可以直接在Java中调用外部动态链接库中的函数!

     

    例子2   

     

        上面那个例子使用了操作系统自带的动态链接库,现在我们再自己写一个动态链接库试试。

     

     

    1,在VS中选择C++语言,然后选择创建一个Win32程序。 选择dll类型。

     

    2,发布的C函数是:

     

    #define MYLIBAPI  extern   "C"     __declspec( dllexport

     

    MYLIBAPI void say(wchar_t* pValue);

     

     

    这个函数的实现是:

     

    void  say(wchar_t* pValue){

         std::wcout.imbue(std::locale("chs"));

     

         std::wcout<<L"上帝说:"<<pValue<<std::endl;

    }

     

    它需要传入一个Unicode编码的字符数组。然后在控制台上打印出一段中文字符。

     

    3,生成dll。然后把生成的dll文件复制到Eclipse项目中,放在项目下面。

    4,在Eclipse中编写以下代码:

     

    import com.sun.jna.Library;

    import com.sun.jna.Native;

    import com.sun.jna.WString;

     

    /**

     * @author 沈东良 Edward Shen shendl_s@hotmail.com

     * 2008-11-23 下午05:07:14

     *TestDll1.dll

     */

    public class TestDll1Service {

     

             public interface TestDll1 extends Library {

                       /**

                        * 当前路径是在项目下,而不是bin输出目录下。

                        */

                       TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);

                       public void say(WString value);

                      

             }

             /**

              *

              */

             public TestDll1Service() {

                       // TODO Auto-generated constructor stub

             }

     

             /**

              * @param args

              */

             public static void main(String[] args) {

                       // TODO Auto-generated method stub

                      

                       TestDll1.INSTANCE.say(new WString("Hello World!"));

                       System.out.println("HHEEH我我们无法万恶");

             }

     

    }

     

    5,执行这个Java类。可以看到控制台下如下输出:

    上帝说:Hello World!

    HHEEH我我们无法万恶

     

    6,上面一行是C语言使用C++std::wcout输出的。

    下面一行是Java语言输出的。

     

     

     

    JNA技术解密

    JNA工作原理

    JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。

    原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。

    JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现JavaC的数据类型映射。你不再需要编写C动态链接库。

    当然,这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。可能速度会降低几倍。但影响不大。

     

    JNA技术难点

     

     

    1,当前路径是在项目下,而不是bin输出目录下。

    2,数据结构的对应关系:

    Java—C和操作系统数据类型的对应表

    Java Type

    C Type

    Native Representation

    boolean

    int

    32-bit integer (customizable)

    byte

    char

    8-bit integer

    char

    wchar_t

    platform-dependent

    short

    short

    16-bit integer

    int

    int

    32-bit integer

    long

    long long, __int64

    64-bit integer

    float

    float

    32-bit floating point

    double

    double

    64-bit floating point

    Buffer
    Pointer

    pointer

    platform-dependent (32- or 64-bit pointer to memory)

    <T>[] (array of primitive type)

    pointer
    array

    32- or 64-bit pointer to memory (argument/return)
    contiguous memory (struct member)

    除了上面的类型,JNA还支持常见的数据类型的映射。

    String

    char*

    NUL-terminated array (native encoding or jna.encoding)

    WString

    wchar_t*

    NUL-terminated array (unicode)

    String[]

    char**

    NULL-terminated array of C strings

    WString[]

    wchar_t**

    NULL-terminated array of wide C strings

    Structure

    struct*
    struct

    pointer to struct (argument or return) (or explicitly)
    struct by value (member of struct) (
    or explicitly)

    Union

    union

    same as Structure

    Structure[]

    struct[]

    array of structs, contiguous in memory

    Callback

    <T> (*fp)()

    function pointer (Java or native)

    NativeMapped

    varies

    depends on definition

    NativeLong

    long

    platform-dependent (32- or 64-bit integer)

    PointerType

    pointer

    same as Pointer

     

     

    JNA编程过程

     

    JNA把一个dll/.so文件看做是一个Java接口。

    DllC函数的集合、容器,这正和接口的概念吻合。

     

        我们定义这样一个接口,

    public interface TestDll1 extends Library {

                       /**

                        * 当前路径是在项目下,而不是bin输出目录下。

                        */

                       TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);

                       public void say(WString value);

                      

             }

     

     

    如果dll是以stdcall方式输出函数,那么就继承StdCallLibrary。否则就继承默认的Library接口。

     

    接口内部需要一个公共静态常量:instance

     

    TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);

     

    通过这个常量,就可以获得这个接口的实例,从而使用接口的方法。也就是调用外部dll的函数!

     

    注意:

    1Native.loadLibrary()函数有2个参数:

        1dll或者.so文件的名字,但不带后缀名。这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。

    搜索dll的路径是:

    1)项目的根路径

    2)操作系统的全局路径、

    3path指定的路径。

     

    2,第二个参数是本接口的Class类型。

     

    JNA通过这个Class类型,根据指定的dll/.so文件,动态创建接口的实例。

     

    2,接口中你只需要定义你需要的函数或者公共变量,不需要的可以不定义。

    public void say(WString value);

     

    参数和返回值的类型,应该和dll中的C函数的类型一致。

    这是JNA,甚至所有跨平台调用的难点。

     

    这里,C语言的函数参数是:wchar_t*

    JNA中对应的Java类型是WStirng

     

     

    所有跨平台、跨语言调用的难点

    有过跨语言、跨平台开发的程序员都知道,跨平台、语言调用的难点,就是不同语言之间数据类型不一致造成的问题。绝大部分跨平台调用的失败,都是这个问题造成的。

    关于这一点,不论何种语言,何种技术方案,都无法解决这个问题。

    这需要程序员的仔细开发和设计。这是程序员的责任。

     

    常见的跨平台调用有:

    1Java调用C语言编写的dll.so动态链接库中的函数。

    2.NET通过P/Invoke调用C语言编写的dll.so动态链接库中的函数。

    3,通过WEBService,在C,C++,Java,.NET等种种语言间调用。

        WebService传递的是xml格式的数据。

     

    即使是强大的P/Invoke或者WebService,在遇到复杂的数据类型和大数据量的传递时,还是会碰到很大的困难。

     

    因为,一种语言的复杂的数据类型,很难用另一种语言来表示。这就是跨平台调用问题的本质。

    如,WEBService调用中,很多语言,如Java.NET都有自动实现的Java/.NET类型和XML类型之间的映射的类库或者工具。

    但是,在现实的编程环境中,如果类型非常复杂,那么这些自动转换工具常常力不从心。

    要么Object-XML映射错误。

    要么映射掉大量的内存。

     

    因此,我个人对这些Object-XML映射框架相当不感冒。

    我现在使用WEBService,都是直接手工使用xml处理工具提取xml中的数据构建对象。或者反过来,手工根据Object中的属性值构建xml数据。

     

     

    JavaC语言之间的调用问题,也是如此。

    Java要调用C语言的函数,那么就必须严格按照C语言要求的内存数量提供Java格式的数据。要用Java的数据类型完美模拟C语言的数据类型。

    JNA已经提供了大量的类型匹配C语言的数据类型。

     

     

     

    跨平台、跨语言调用的第一原则:就是尽量使用基本、简单的数据类型,尽量少跨语言、平台传递数据!

    只有你才能拯救你自己。

    如果在你的程序中,有复杂的数据类型和庞大的跨平台数据传递。那么你必须另外写一些Façade接口,把需要传递的数据类型简化,把需要传递的数据量简化。

    否则,不论是实现的难度还是程序的性能都很难提高。

     

     

     

     

    JNI还是不能废

    我们已经见识了JNA的强大。JNI和它相比是多么的简陋啊!

    但是,有些需求还是必须求助于JNI

    JNA是建立在JNI技术基础之上的一个框架。

    使用JNI技术,不仅可以实现Java访问C函数,也可以实现C语言调用Java代码。

    JNA只能实现Java访问C函数,作为一个Java框架,自然不能实现C语言调用Java代码。此时,你还是需要使用JNI技术。

    JNIJNA的基础。是JavaC互操作的技术基础。

     

     

    展开全文
  • python 调用so dll动态链接库

    千次阅读 2012-09-09 19:28:58
    ctypes使得python能够直接调用c语言开发的动态链接库,非常强大。 为了使用CTypes,你必须依次完成以下步骤: * 编写动态连接库程序 * 载入动态连接库 * 将Python的对象转换为ctypes所能识别的参数 * 使用...
  • python py生成及调用pyd(so)文件

    万次阅读 2021-03-05 00:30:04
    本文仅供学习交流使用,如侵立删!联系方式及demo下载见文末 py文件生成pyd文件 1.安装 cython:注意不是cpython pip install cpython 2.py文件生成pyd文件 ...会在当前目录下的 ./build/lib.win-a
  • String ext = (systemType.toLowerCase().indexOf("win") != -1) ? ".dll" : ".so"; while (dir.hasMoreElements()) { URL url = dir.nextElement(); String protocol = url.getProtocol(); if ("jar".equals...
  • 问题描述: Java项目,做中间件的,之前是在Linux系统下开发,用JNI调用内核部提供的.so文件,但是现在又要Windows系统下测试运行情况,所以提出了题目中的问题:怎么在Windows下使用eclipse java程序调用.so文件?...
  • 现在我有一个Java项目,是win系统下面,因为项目需求,需要调用.so文件去将.dat文件转换成.txt文件。因整个项目都在win下,没办法再提供Linux环境去运行.so文件。有没有方法直接在java项目中集成调用.so文件?我使用...
  • Make成python可以调用的.so文件,并且包含例子。Make成python可以调用的.so文件,并且包含例子。
  • java 调用win32 api 学习总结

    万次阅读 2016-03-18 09:06:48
    java使用JInvoke调用windows API 使用jinvoke调用windowsAPI。...官网使用参考:http://www.jinvoke.com/calling-the-win32-api-from-java  一个弹出框的例子(这种代码用于调用任何dll,不只是windows的
  • Python调用win32api

    万次阅读 2014-03-11 21:39:11
    首先安装Python, 我安装的是Python2.7 其次就是安装Pywin32, 在... 注意第一点就是这里的版本是要和python的版本相依赖的,我下载的是pywin32-218.win32-py2.7.exe 编写我自己的程序: import
  • Android调用不符合JNI命名规范的so

    千次阅读 2017-10-13 16:03:15
    现在有一个纯c++风格的arm平台的动态链接库libbytebuffer.so和头文件ByteBuffer.h,接下来我将先将其封装成符合JNI命名规范的so库,这样JNI能直接调用,然后将JNI层的代码制作成jar包,然后再给Android App调用。...
  • Java的JNA调用C语言的So动态链接库

    千次阅读 2018-06-22 14:22:28
    Java的JNA调用C++的So动态链接库 Java的JNA调用C++的So动态链接库 JNA简介 JNA技术原理 JNA链接 JNA Examples JNA demo 编写So 设置JNA的jar包 编写Java 参考链接 JNA简介 先说JNI(Java Native ...
  • JNA调用C++ DLL|SO库文件

    千次阅读 2020-12-03 20:37:20
    JNA是对JNI调用的封装 需要使用C/C++调用Java时 需使用JNI调用 JNI调用参考 https://blog.csdn.net/setlilei/article/details/114751858 动态链接库文件文件获取 或 手动编译动态链接库文件 import ...
  • 关于动态调用动态库方法说明 一、 动态库概述 1、 动态库的概念 日常编程中,常有一些函数不需要进行编译或者可以在多个文件中使用(如数据库输入/输出操作或屏幕控制等标准任务函数)。可以事先对这些函数...
  • 能够象win平台那样,在linux平台下也能完成nodejs对.so动态库的调用。 谢谢 附图:![图片说明](https://img-ask.csdn.net/upload/201808/01/1533088367_853647.jpg) ![图片说明]...
  • Android Java调用libtwolib-first.a 输入: 新建jni目录,放入libtwolib-first.a、first.h、second.c、Android.mk四个文件 输出: libtwolib-second.so(打包进apk了)、Caculator.apk 过程: Android.mk内容...
  • Qt Creator调用C语言编译的.So动态库

    千次阅读 2016-03-23 10:40:08
    动态库是libS8.so,头文件是s8.h。  刚开始做的时候,使用QLibrary进行加载这个动态库,发现始终加载不到,带着郁闷去问了卖家~结果他们说搞这个产品的工程师离职了,这实在太坑了。  没办法,我只能自食其力了,上...
  • 由MessageBox透视Win32 API的调用

    千次阅读 2014-08-23 17:00:39
    下面我们来看看Windows平台下应用程序是怎么调用Windows提供的底层API服务运行的。 我们编写Win32SDK程序时,需要弹出对话框以作出友好的选择,MessageBox这个API函数就可以实现该功能。在开头要添加,因为其包含了...
  • CMake再探:引入SO文件并调用

    万次阅读 2017-07-12 16:31:18
    上次已经通过CMake编译自己写的C/C++代码了,这次尝试导入第三方代码来进行调用。通过上次写的JniTest生成的so文件来测试,生成的so文件在项目的app/build/intermediates/cmake/debug/obj目录下。 1.导入so文件 将...
  • python调用window dll和linux so例子

    千次阅读 2017-01-09 11:46:40
    #!/usr/bin/python # -*- coding: UTF-8 -*- #python dll.py import win32api # 打开记事本程序,在后台运行,即显示记事本程序的窗口 win32api.ShellExecute(0, 'open', 'notepad.exe', '','...win32process.CreatePro
  • 问题描述 win10环境下VS编译完成后,JNA调用DLL报“调用dll %1 不是有效的win32应用程序”错误。 解决方案 VS编译目标设置为x64即可解决问题。
  • 基于海康windows下的.dll和Linux下的.so动态库调用 上一篇:基于海康SDK开发文档分析+云台控制实现+经典案例 最近在做海康摄像头的二次开发,在将项目部署在Linux上面的时候遇到了调用动态库的问题,下面只解释怎样...
  • linux与windows调用动态库so dll文件

    千次阅读 2015-04-17 22:30:51
    关于动态调用动态库方法说明 一、 动态库概述 1、 动态库的概念 日常编程中,常有一些函数不需要进行编译或者可以在多个文件中使用(如数据库输入/输出操作或屏幕控制等标准任务函数)。可以事先对这些函数...
  • 动态调用动态库方法 .so

    千次阅读 2012-03-28 10:38:36
    关于动态调用动态库方法说明 一、 动态库概述 1、 动态库的概念 日常编程中,常有一些函数不需要进行编译或者可以在多个文件中使用(如数据库输入/输出操作或屏幕控制等标准任务函数)。可以事先对这些函数进行...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,295
精华内容 15,718
关键字:

win调用so