代码之家  ›  专栏  ›  技术社区  ›  Chris

JNA-从返回的指针调用来自DLL的Strut的本机C++函数

  •  0
  • Chris  · 技术社区  · 6 年前

    我的问题是如何从一个结构调用一个函数,该结构作为从初始调用到本机c++函数的指针返回。(我还没有发展.dll)

    猜测c++导出函数

    extern "C" __declspec(dllexport) unsigned int MTManagerVersion(int &version) { 
    // some c++ code
    }
    
    extern "C" __declspec(dllexport) unsigned int MTManagerCreate(int version, ManagerAPI **managerAPI) {
    // some c++ code
    }
    

    在Java世界中,我做了以下工作:

    加载本机dll文件并定义dll导出函数。

    public interface MTManagerAPIFactory extends Library {
    
    MTManagerAPIFactory INSTANCE = Native.load(".\\MT5APIManager64.dll", ManagerAPIFactory.class);
    
        int MTManagerVersion(IntByReference version);
    
        int MTManagerCreate(int version, PointerByReference pointer);
    }
    

    定义指针引用结构的类。请注意,该结构只包含函数,甚至不包含单个字段/变量。

    @Structure.FieldOrder({"Disconnect", "Connect"})
    public class IMTManagerAPI extends Structure implements Structure.ByReference {
    
        public IMTManagerAPI() {
            super();
        }
    
        public IMTManagerAPI(Pointer address) {
            super(address);
            read();
        }
    
        public interface Connect extends Callback {
    
            public int Connect(String server, int login, String password, String password_cert, int pump_mode, int timeout);
        }
    
        public interface Disconnect extends Callback {
    
            void Disconnect();
        }
    
        public Disconnect Disconnect;
        public Connect Connect;
    }
    

    终于把所有的东西都拼在一起了。

    public static void main(String[] args) {
    int response;
    
    // get version
    IntByReference version = new IntByReference();
    response = MTManagerAPIFactory.INSTANCE.MTManagerVersion(version);
    System.out.println(String.format("ManagerAPI Version %s (response %s)", version.getValue(), response));
    
    // create manager api
    PointerByReference managerAPIByReference = new PointerByReference();
    response = MTManagerAPIFactory.INSTANCE.MTManagerCreate(version.getValue(), managerAPIByReference);
    System.out.println(String.format("ManagerAPI Create(response %s)", response));
    
    if (managerAPIByReference.getValue() == null) {
        System.out.println("\nWARN: Return pointer is null..\n");
    }
    IMTManagerAPI manager = new IMTManagerAPI(managerAPIByReference.getValue());
    // invalid memory access
    manager.Disconnect.Disconnect();
    }
    

    运行应用程序后,我得到以下结果:

    ManagerAPI版本1881(响应0)

    创建ManagerAPI(响应0)

    线程“main”中的异常java.lang.Error错误:无效的内存访问 com.sun.jna网站.本机.invokeVoid(本地方法)在 com.sun.jna网站.函数.invoke(函数java:414)在 com.sun.jna网站.函数.invoke(函数java:360)在 com.sun.jna网站.函数.invoke(java:314函数)在 com.sun.jna网站.回调引用$NativeFunctionHandler.invoke(java:679) 在com.sun.proxy网站.$Proxy3.断开连接(未知源) 在应用程序主(java应用程序:28)

    注意:虽然我不想使用回调,但我没有找到其他方法来调用结构中的函数。

    任何想法/帮助谢谢!

    P、 我读过很多关于堆栈溢出的类似答案,没有运气。

    可以找到Update#1 Manager API头 here

    0 回复  |  直到 6 年前