当前位置:网站首页>[hybrid programming JNI] details of JNA in Chapter 11

[hybrid programming JNI] details of JNA in Chapter 11

2022-06-26 22:07:00 Hua Weiyun

continue JNA Understanding , If you don't know JNA What is it? , You can read my last article

Mapping of functions

Interface mapping

adopt Native.load() When loading the dynamic library , The function corresponding to the dynamic library directly through the interface ,

because JNA Will create a proxy , agent invoke adopt Library.Handler. Find the matching function in the exported method table .

Direct mapping

JNA Provides a direct registration method , If there are native , Marked as native Function call for .

You can use it directly Native.register() Register your method

Data type mapping

Base types are mapped directly , Because of the same size

image.png

Use pointers and arrays

Raw array parameters ( Including structure ) They correspond to Java Type said . for example :

// original  C  Statement  void fill_buffer ( int *buf, int len); void fill_buffer ( int buf[], int len); // Same syntax as array  // The equivalent of  JNA  mapping  void fill_buffer( int [] buf, int len);

Be careful : If the parameter is to be used by a native function outside the scope of the function call , Must be used Memory or NIO Direct buffer .Java The memory provided by the original array is only valid for use by native code during function calls .

C Array of strings ( for example char* argv[]Cmain Of ) It can be used String[]Java Code representation .JNA Will be automatically passed with NULL An equivalent array of final elements .

Use structure and union

When a function needs a pointer to a structure ,Java You should use Structure. If the structure is passed or returned by value , You only need to modify the parameter or return type class declaration slightly .

The definition class inherits from Structure,. And must be FieldOrder The list returned by the annotation or method contains the field names of each declaration in order getFieldOrder().

If the function requires an array of structures ( Continuously allocate... In memory ), Java have access to Structure[.

Pass in The array is Structure when , There is no need to initialize the array elements ( The function call will assign you 、 Zero memory and allocate elements ).

If you really need to initialize the array , Then use this Structure.toArray Method to obtain an array of contiguous structural elements in memory , It can then be initialized as needed .

Unions It is usually possible to communicate with Structures swap , But you are required to setType Method to indicate which union field is active before it is correctly passed to the function call .

If you have a particularly long or complex structure , You may consider using the Olivier Chafik Compiling JNAerator Tools , It can generate for you JNA mapping .

Use ByReference Parameters

When a function accepts a pointer to a type parameter , You can use one of these ByReference Type to capture the return value , Or subclass your own values . for example :

// original  C  Statement void  allocate_buffer ( char **bufp, int * lenp);// The equivalent of  JNA  mapping void allocate_buffer(PointerByReference bufp, IntByReference lenp);
// UsagePointerByReference pref = new PointerByReference();IntByReference iref = new IntByReference();lib.allocate_buffer(pref, iref);Pointer p = pref.getValue();byte[] buffer = p.getByteArray(0, iref.getValue());

You can use... With a single element of the desired type Java Array , but ByReference Conventions better communicate the intent of the code .Pointer except getByteArray() Effectively cast as a type out of memory , This class also provides many accessor methods .

PointerType You can declare a type safe pointer by deriving from a class .

Whole point example

1、 Array An example of an array , Just use the example above

c++ The header file

#ifndef TESTJNA_TEST_H#define TESTJNA_TEST_H#define PDOOL_API extern "C" __declspec( dllexport )PDOOL_API int sum(int a, int b);PDOOL_API void fill_buffer(int buf[], int len);#endif //TESTJNA_TEST_H

c++ Realization

Here we just print out all the array elements

#include "test.h"#include "iostream"int sum(int a ,int b){    return a +b;} void fill_buffer(int buf[], int len){    for (int i = 0;i<len;i++){        std::cout<<buf[i];    }}

Generate the above code dll copy to java Project resource Catalog ,

If not, you can read my previous article

look down java Implementation of the side

import com.sun.jna.Library;import com.sun.jna.Native;/** *  Dynamic library interface  * @author xin.chong */public interface Lib extends Library {    Lib INSTANCE = Native.load( "testJNA.dll", Lib.class);    int sum(int a,int b);     void fill_buffer(int[] buf, int len);}

Look at the call

/** * Hello world! * */public class App {    public static void main(String[] args) {        int result = Lib.INSTANCE.sum(1,3);        System.out.println(" Congratulations ,JNA  The first program succeeded  ,the  result is  "+ result);        int[] arr = {1,2,3,4,5};        Lib.INSTANCE.fill_buffer(arr,arr.length);    }}

Look at the printout

image.png

Array calls are simple , Of course, this is just an array of basic types , The complicated ones will be discussed later , continue !

2、 Structure

A structure is a complex custom structure , So it is still troublesome to deal with , Let's take a look at Java How to simulate the

c++ Side Define a player structure

#ifndef TESTJNA_TEST_H#define TESTJNA_TEST_H#define PDOOL_API extern "C" __declspec( dllexport ) struct PlayerStruct{    long id;    wchar_t* name;    int age;}; PDOOL_API int sum(int a, int b); PDOOL_API void fill_buffer(int buf[], int len); PDOOL_API void createPlayer(PlayerStruct* pUserStruct); #endif //TESTJNA_TEST_Hcpp  Realization void createPlayer(PlayerStruct* pPlayerStruct){    std::cout<<pPlayerStruct->id <<" "<< pPlayerStruct->name <<"  "<<pPlayerStruct->age;}

Java Implementation of the side

First create a class that inherits from Structure and C++ Side for corresponding mapping

import com.sun.jna.Structure; import java.util.Arrays;import java.util.List; public class PlayerStruct extends Structure {    public long id;    public String name;    public int age;    public static class ByReference extends PlayerStruct implements Structure.ByReference {}    public static class ByValue extends PlayerStruct implements Structure.ByValue {}    @Override    protected List<String> getFieldOrder() {        return Arrays.asList(new String[] { "id", "name", "age"});    }}

Be careful :

It has to be inherited Structure getFieldOrder The returned field list should be the same as C++ Side to side , The order must not be disordered , Corresponding c++ Side memory order ByReference Corresponding c++ Side structure pointer ByValue Is the value of the structure



原网站

版权声明
本文为[Hua Weiyun]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/177/202206262200389431.html