学习园

c++ 中的结构体转换为对应的java类

将c++的结构体,函数方法转化为java对应的java,对于复杂的c++代码如果手动写,可能要写到天荒地老。这里采用了jnaerator 的工具包,进行转化。如果c++代码是自己写的,比较简单的话可以自己写对应的java文件。

使用方式:

参数水明

参数说明:

-runtime JNA

指定目标运行库为JNA,
-runtime 可选的值有(区分大小写)
JNA
JNAerator (based on JNA)

-mode Maven

指定输出模式为Maven
-mode可选的值(区分大小写):
Jar : JAR 生成jar包,可以使用-jar指定生成的jar包文件名
StandaloneJar : 生成包含所有依赖库的jar ,可以使用-jar指定生成的jar包文件名
Directory : 生成代码到文件夹
Maven : 生成maven格式的项目(pom.xml)
AutoGeneratedMaven : 生成maven格式的项目(pom.xml),执行mave install 自动编译生成jar包,不生成源码

-mavenGroupId net.gdface

指定 maven项目的 groupId

-mavenArtifactId cassdk_jna

指定 maven项目的 artifactId

-o jna_code

指定输出文件夹 jna_code

-package net.gdface.jna

指定生成java代码的包名。如果不指定,则默认包名为 library name

-f

生成代码时强制覆盖已经存在的文件

-library THFaceImage -library THFeature

指定后面的动态库的名称(library name),在这里为”THFeature.dll”,如果不指定则library name 为 头文件名称:‘THFeature_i’,
NOTE:-library就是个状态参数,只对其后面的文件名参数有效,所以这里用两次-library分别为THFeature_i.h和THFeature_i.h指定了不同的动态库名称

bin\THFeature.dll include\THFeature_i.h bin\THFeature.dll include\THFeature_i.h

指定要生成代码的动态库和对应头文件,前后顺序无关,可以不提供动态库文件名称,只需要.h文件就可以生成JNA代码

数据结构转化参考文档

c++ demo

本人于c++属于未入门级别,c++代码是在网上找的,如下


/*
 * =====================================================================================
 *
 *       Filename:  TestDll1.cpp
 *
 * =====================================================================================
 */
#include <string.h>
#include <wchar.h>

#define MYLIBAPI extern "C"

MYLIBAPI void say(wchar_t *pValue);

struct UserStruct{
    long     id;
    wchar_t    *name;
    int     age;
};

MYLIBAPI void sayUser(UserStruct *pUserStruct);

struct CompanyStruct{
    long     id;
    wchar_t *name;
    UserStruct users[100];
    int count;
};

struct CompanyStruct2{
    long     id;
    wchar_t    *name;
    UserStruct *users[100];
    int count;
};
#pragma pack(1)
struct NestedStruct{
    char pwd[16];
    char key[16];
    char padding[113];
};

struct SimpleStruct{
    NestedStruct nested;
    int a;
    unsigned char b;
    int c;
    int d;
    char name[100];
};
#pragma pack()
MYLIBAPI void sayCompany(CompanyStruct* pCompanyStruct);
MYLIBAPI void sayCompany2(CompanyStruct2 *pCompanyStruct);
MYLIBAPI void getCompany(CompanyStruct *pCompanyStruct);
MYLIBAPI void getSimpleStruct(SimpleStruct *simp);
MYLIBAPI void saySimpleStruct(SimpleStruct *simp);

#include <iostream>

void say(wchar_t *pValue){
    std::wcout<<L"上帝说: "<<pValue<<std::endl;
}

void sayUser(UserStruct *pUserStruct){

    std::wcout<<L"ID: "<<pUserStruct->id<<std::endl;
    std::wcout<<L"姓名: "<<pUserStruct->name<<std::endl;
    std::wcout<<L"年龄: "<<pUserStruct->age<<std::endl;
}

void sayCompany(CompanyStruct *pCompanyStruct){

    std::wcout<<L"ID: "<<pCompanyStruct->id<<std::endl;
    std::wcout<<L"公司名称: "<<pCompanyStruct->name<<std::endl;
    std::wcout<<L"员工总数: "<<pCompanyStruct->count<<std::endl;

    for (int i = 0; i < pCompanyStruct->count; i++){
        sayUser(&pCompanyStruct->users[i]);
    }

}

void sayCompany2(CompanyStruct2 *pCompanyStruct){


    std::wcout<<L"ID: "<<pCompanyStruct->id<<std::endl;
    std::wcout<<L"公司名称: "<<pCompanyStruct->name<<std::endl;
    std::wcout<<L"员工总数: "<<pCompanyStruct->count<<std::endl;

    for (int i = 0; i < pCompanyStruct->count; i++){
        sayUser(pCompanyStruct->users[i]);
    }
}

void getCompany(CompanyStruct *pCompanyStruct){
    pCompanyStruct->count = 1;
    wcscpy(pCompanyStruct->name, L"Out Name");
    pCompanyStruct->id = 13;
}

void getSimpleStruct(SimpleStruct *simp){
    simp->a = 1;
    simp->b = 2;
    simp->c = 3;
    simp->d = 4;
    memset(simp->name, 0, sizeof(simp->name));
    strcpy(simp->name, "test");
    memset(&simp->nested, 0, sizeof(NestedStruct));
    strcpy(simp->nested.pwd, "pwd");
    strcpy(simp->nested.key, "key");
}

void saySimpleStruct(SimpleStruct *simp){
    std::wcout<<L"simp->a = "<<simp->a<<std::endl;
    std::wcout<<L"simp->b = "<<simp->b<<std::endl;
    std::wcout<<L"simp->c = "<<simp->c<<std::endl;
    std::wcout<<L"simp->d = "<<simp->d<<std::endl;
    std::wcout<<L"simp->name = "<<simp->name<<std::endl;
    std::wcout<<L"simp->nested.pwd ="<<simp->nested.pwd<<std::endl;
    std::wcout<<L"simp->nested.key ="<<simp->nested.key<<std::endl;
}


c++文件生成的java代码:

备注: 这个文件不是使用jnaerator 工具生成的,工作中实际生成过,亲测可用,涉及到公司机密,源文件不便放出。这个cpp文件由于没有h文件,所以没生成,java文件为网上找到的。

参考java文件地址

//package com.sun.jna;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Structure;
import com.sun.jna.WString;


public class TestDll1Service {

     /*
      * 定义一个类,模拟C语言的结构
      *
      */

       public static class UserStruct extends Structure{

            public static class ByReference extends UserStruct implements Structure.ByReference {
                public ByReference() {}
                //public ByReference(Pointer p){ super(p);}
            }
            public static class ByValue extends UserStruct implements Structure.ByValue {
                public ByValue() {}
                //public ByValue(Pointer p) { super(p);}
            }

           public NativeLong id;
           public WString name;
           public int age;

           // 字段顺序与SO中结构体声明一致
           protected List getFieldOrder() {
            return Arrays.asList(new String[] {
            "id", "name", "age"
                });
            }
       }

       public static class CompanyStruct extends Structure{
            public static class ByReference extends CompanyStruct implements Structure.ByReference {
                public ByReference() {}
                //public ByReference(Pointer p){ super(p);}
            }

            public static class ByValue extends CompanyStruct implements Structure.ByValue {
                public ByValue() {}
                //public ByValue(Pointer p) { super(p);}
            }

           public NativeLong id;
           public WString  name;
           // 嵌套的结构体数组,下面三种声明都可以,注意每种声明的赋值方式
           // Declare 1
           // public UserStruct[] users = (UserStruct[])new UserStruct().toArray(100);
           // Declare 2
           // public UserStruct.ByValue[] users = new UserStruct.ByValue[100];
           // Declare 3
           public UserStruct[] users = new UserStruct[100];
           public int count;

           protected List getFieldOrder() {
            return Arrays.asList(new String[] {
            "id", "name", "users", "count"
                });
            }


       }

       public static class CompanyStruct2 extends Structure{
           public static class ByReference extends CompanyStruct2 implements Structure.ByReference {
                public ByReference() {}
                //public ByReference(Pointer p){ super(p);}
           }

           public static class ByValue extends CompanyStruct2 implements Structure.ByValue {
                public ByValue() {}
                //public ByReference(Pointer p){ super(p);}
            }

           public NativeLong id;
           public WString  name;
             // 嵌套的结构体指针数组
           public UserStruct.ByReference[] users=new UserStruct.ByReference[100];
           public int count;

           protected List getFieldOrder() {
            return Arrays.asList(new String[] {
            "id", "name", "users", "count"
                });
            }


       }

       public static class NestedStruct extends Structure{
               public static class ByValue extends NestedStruct implements Structure.ByValue{}
               // 声明内存对齐方式,与SO中声明的结构体对齐保持一致
            public NestedStruct() {super(ALIGN_NONE);}

            // 注意C/C++中的char 对应java中的byte,其它类型之间的映射请参考官方文档
            public byte pwd[] = new byte[16];
            public byte key[] = new byte[16];
            public byte padding[] = new byte[113];

            protected List getFieldOrder(){
                return Arrays.asList(new String[]{
                    "pwd", "key", "padding"});
            }
       }

       public static class SimpleStruct extends Structure{
        public static class ByReference extends SimpleStruct implements Structure.ByReference{}
        public NestedStruct.ByValue nested = new NestedStruct.ByValue();
           public int a;
           public byte b;
           public int c;
           public int d;
        public byte name[] = new byte[100];

        public SimpleStruct(){super(ALIGN_NONE);};
           protected List getFieldOrder(){
               return Arrays.asList(new String[]{
               "nested", "a", "b", "c", "d", "name"
               });
        }
       }


        public interface TestDll1 extends Library {
           /**
            * 当前路径是在项目下,而不是bin输出目录下。
            */
            TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);


            public void say(WString value);



            public void sayUser(UserStruct.ByReference struct);



             public   void sayCompany(CompanyStruct.ByReference pCompanyStruct);

            public void sayCompany2(CompanyStruct2.ByReference  pCompanyStruct);

            //public void getCompany(CompanyStruct.ByReference pCompanyStruct);
            public void getSimpleStruct(SimpleStruct simp);
            public void getSimpleStruct(SimpleStruct.ByReference simp);
            public void saySimpleStruct(SimpleStruct simp);

        }
    public class TestClass{
        int a;
        int b;
    }


    /**
     * @param args
     */
    public static void main(String[] args) {
       // TODO Auto-generated method stub

       TestDll1.INSTANCE.say(new WString("Hello World!"));
       System.out.println("HHEEH中文");


       UserStruct.ByReference userStruct = new UserStruct.ByReference();
       userStruct.id = new NativeLong(100);
       userStruct.age = 30;
       userStruct.name = new WString("yifan");
       TestDll1.INSTANCE.sayUser(userStruct);
       System.out.println("AAAAAAAAAAAAAAAAAAAAAAAAAAA");

       CompanyStruct.ByReference companyStruct = new CompanyStruct.ByReference();
       companyStruct.id = new NativeLong(1);
       companyStruct.name = new WString("Google");
       companyStruct.count = 9;
       System.out.println("UserStruct size = " + userStruct.size());
       System.out.println("CompanyStruct size = " + companyStruct.size());
       for(int i = 0; i < companyStruct.count; i++){
           /*
            * Declare 1
           companyStruct.users[i].id = new NativeLong(i);
           companyStruct.users[i].name = new WString("yifan" + i);
           companyStruct.users[i].age = 20 + i;
           */
           /*
            * Declare 2
           UserStruct.ByValue user = new UserStruct.ByValue();
           user.id = new NativeLong(i + 1);
           user.name = new WString("yifan" + i);
           user.age = 20 + i;
           companyStruct.users[i] = user;
           */
           /*
            * Declare 3
            */
           UserStruct user2 = new UserStruct();
           user2.id = new NativeLong(i);
           user2.name = new WString("yifan " + i);
           user2.age = 20 + i;
           companyStruct.users[i] = user2;
       }
       TestDll1.INSTANCE.sayCompany(companyStruct);

       System.out.println("++++++++++++++");

       CompanyStruct2.ByReference companyStruct2 = new CompanyStruct2.ByReference();
       companyStruct2.id = new NativeLong(2);
       companyStruct2.name = new WString("Yahoo");
       companyStruct2.count = 10;
       System.out.println("CompanyStruct2 size = " + companyStruct2.size());
       for(int i = 0;i < companyStruct2.count; i++){
            companyStruct2.users[i] = new UserStruct.ByReference();
               companyStruct2.users[i].id = new NativeLong(i);
            companyStruct2.users[i].name = new WString("Yahoo user" + i);
            companyStruct2.users[i].age = 20 + i;
       }
       //companyStruct.write();
       TestDll1.INSTANCE.sayCompany2(companyStruct2);

       System.out.println("CCCCCCCCCCCCCCCCCCCCCCCCCCCC");
       SimpleStruct.ByReference simple = new SimpleStruct.ByReference();
       TestDll1.INSTANCE.getSimpleStruct(simple);
       System.out.println("simple: size = " + simple.size());
       System.out.println("simple: a = " + simple.a);
       System.out.println("simple: b = " + simple.b);
       System.out.println("simple: c = " + simple.c);
       System.out.println("simple: d = " + simple.d);
       System.out.println("simple: name = " + new String(simple.name));
       System.out.println("simple: nested: pwd = " + new String(simple.nested.pwd));
       System.out.println("simple: nested: key = " + new String(simple.nested.key));
       System.out.println("DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD");

       SimpleStruct simp2 = new SimpleStruct();
       byte[] pwd = "simp2_pwd".getBytes();
       byte[] key = "simp2_key".getBytes();
       byte[] name = "simp2".getBytes();
       simp2.a = 5;
       simp2.b = 6;
       simp2.c = 7;
       simp2.d = 8;
       //
       // 对于已经声明大小的数组,使用下面数组赋值方式,
       // 不要使用simp2.nested.pwd = "11".getBytes() 这种赋值方式
       //

       System.arraycopy(name, 0, simp2.name, 0, name.length);
       System.arraycopy(pwd, 0, simp2.nested.pwd, 0, pwd.length);
       System.arraycopy(key, 0, simp2.nested.key, 0, key.length);
       TestDll1.INSTANCE.saySimpleStruct(simp2);
       System.out.println("EEEEEEEEEEEEEEEEEEEEEEEEEEEEE");


    }

}

实际工作中是客户给的c++ 文件有c++头文件和 .so文件,涉及公司机密,就不上贴源码,这里只讲述整体流程,代码案例就使用简单demo。

根据c++ 代码生成so文件

g++ -fPIC -shared -o libhello.so hello.cpp
注意: 这里需要在c++环境。我是在linux下执行的,整理调用也是在linux下完成的。生成的
	so文件要加上lib,因为加载系统文件时默认是寻找lib开头的文件。如: (Clibrary) Native.loadLibrary("hello",Clibrary.class); 系统其实是去寻找libhello文件,所以在生成so文件时,记得加上lib前缀。

写一个controller接口

将生成的java代码放在springboot项目中,在controller接口中调用java接口,进而调到对应c++接口 

如下:

package cjc.cpp.test.mydemo;

import com.sun.jna.NativeLong;
import com.sun.jna.WString;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: mubai
 * @Date: 2020-10-23 09:38
 * @Description:
 */

@RestController
@RequestMapping("/demo")
public class DemoController {

    @GetMapping("/demo")
    public String demo() {
        // TODO Auto-generated method stub
        try {
            TestDll1Service.TestDll1.INSTANCE.say(new WString("Hello World!"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("HHEEH中文");
        return "Hello World ! ";

    }

    @GetMapping("/test")
    public String test() {
        // return Service.instance.say();
        return new Service().say();
    }

    public String say() {
        return " hello";
    }
}

将项目放在linux下执行

通过java -jar 将项目启动,调用http接口,进而调通了c++接口,展示效果如下:
在这里插入图片描述

注意:

   这里需要特别注意,当时一致包找不到class文件,或无法加载到指定的文件。当时网上查了很多资料,so文件也放在了 /usr/lib 下了,直到看到一个博客说,要将so文件放在/usr/lib64 下面,因为我使用的机器是64为机器,jdk8,加载系统文件默认是到该目录下加载。

如有问题欢迎咨询,有错误的地方欢迎指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值