简体   繁体   English

使用JNA访问DLL:输出未按预期顺序

[英]Using JNA to access DLL: Output not in expected order

Background first, PROBLEM in bold: 背景优先, PROBLEM以粗体显示:

I am a student and for a summer research project, I am going to write a Java program that lets me export data collected from research hardware into MATLAB in the Windows environment-- I don't need the program to be portable to other platforms. 我是一名学生,并且在一个暑期研究项目中,我将编写一个Java程序,使我可以将在Windows环境中从研究硬件收集的数据导出到MATLAB中-我不需要将该程序移植到其他平台上。 I have a third-party DLL with a great API containing C/C++ declarations, but I don't have access to the source code for the DLL. 我有一个第三方DLL,它的API很好,包含C / C ++声明,但是我无法访问该DLL的源代码。

I only know Java, so after looking at the available options, I decided to use JNA because it seemed easiest and most straightforward to use, plus, JNA is currently maintained. 我只知道Java,所以在查看了可用的选项后,我决定使用JNA,因为它似乎最容易使用,而且最直接,而且目前仍在维护JNA。 I asked a friend who knows C++ make an example DLL for me so I could start at the bottom and make a "hello world" style test of loading the library and accessing native methods using JNA. 我问一个知道C ++为我创建示例DLL的朋友,所以我可以从头开始,进行“ hello world”风格的测试,以加载库并使用JNA访问本机方法。 I followed examples from here -- and read about a hundred responses to other people's questions by twall and/or technomage. 我从这里跟踪了一些示例,并通过twall和/或技术了解了大约一百种对他人问题的回答。

After working around some UnsatisfiedLinkErrors due to jna.library.path starting as null , I recompiled the 32-bit example DLL given to me into 64-bit, and threw them both into the /bin folder, and I let the program determine which one to access, depending on the JVM running. 解决了由于jna.library.path以null开头而导致的一些UnsatisfiedLinkErrors之后,我将提供给我的32位示例DLL重新编译为64位,然后将它们都放入/ bin文件夹,然后由程序确定哪个访问,具体取决于运行的JVM。 I know I won't be able to do this with my third party DLL, which is 32-bit, but this is just part of my proof of concept phase. 我知道我将无法使用32位第三方DLL来执行此操作,但这只是我的概念验证阶段的一部分。

I have been able to access the DLL methods easily enough, but I am seeing output-- all print statements-- in an unexpected order. 我已经能够足够容易地访问DLL方法,但是我看到输出-所有打印语句-都以意外的顺序出现。 What it looks like is that my Java code is executing start to finish, then the native library start to finish 看起来是我的Java代码开始执行,然后本机库开始执行

Later in my project, I will need to call native functions, then java methods, then native functions again, so I need to understand what is causing this odd sequence early on. 在我的项目的稍后部分,我将需要先调用本机函数,然后再调用java方法,然后再调用本机函数,因此我需要尽早了解是什么导致了这种奇怪的序列。 I tried a very procedural approach at first; 一开始我尝试了一种非常程序化的方法; below is my attempt to dress the methods up as objects I can manipulate, which yielded the same results. 下面是我尝试将这些方法装扮成我可以操纵的对象的方式,产生了相同的结果。 I am guessing it has to do with HOW the JVM and the native side of the house interact, or the differences in the way windows and Java handle I/O, but I am stumped on what is causing it, or how to approach the issue. 我猜想这与JVM和房屋的本机端如何交互或Windows和Java处理I / O方式的差异有关,但我对导致它的原因或如何解决问题感到困惑。

My setup looks like this: // CallFooPortably.java 我的设置如下所示:// CallFooPortably.java

public class CallFooPortably { //name taken from a tutorial, thanks!
    public static void main(String[] args) {
        System.out.println("MIAN START");// debug test
        System.setProperty("jna.library.path",System.getProperty("java.class.path"));
        System.out.println("MAIN Break1");// debug test
        methodOneClass objectA=new methodOneClass();
        objectA.methodOne();
        System.out.println("MAIN inter-method");// debug test
        objectA.methodTwo();
        System.out.println("MAIN END");// debug test
    }
}

My methods that call the libraries are here: // methodOneClass.java 我的调用库的方法在这里:// methodOneClass.java

public class methodOneClass{

      public methodOneClass(){
            System.out.println("Object Created!");
      }

      public void methodOne()  {
            String temp1 = System.getProperty("sun.arch.data.model");
            //provides the JVM bit-ness to the program 

            if (temp1.equals("32")) {
                  System.out.println("Break2");// debug test
                  UserDllLInterface.CLibrary.INSTANCE.Export1();
                  System.out.println("Break3");// debug test
                  UserDllLInterface.CLibrary.INSTANCE.Export2();
                  System.out.println("Break4");// debug test

            } else if (temp1.equals("64")) {
                  System.out.println("Break5");// debug test
                  UserDllLInterface.x64_CLibrary.INSTANCE.Export1();
                  System.out.println("Break6");// debug test
                  UserDllLInterface.x64_CLibrary.INSTANCE.Export2();
                  System.out.println("Break7");// debug test
            }
      }

      public void methodTwo()  {
            String temp2 = System.getProperty("sun.arch.data.model");
            if (temp2.equals("32")) {
                  System.out.println("Break8");// debug test
                  UserDllLInterface.CLibrary.INSTANCE.Export1();
                  System.out.println("Break9");// debug test
                  UserDllLInterface.CLibrary.INSTANCE.Export2();
                  System.out.println("Break10");// debug test
            } else if (temp2.equals("64")) {
                  System.out.println("Break11");// debug test
                  UserDllLInterface.x64_CLibrary.INSTANCE.Export1();
                  System.out.println("Break12");// debug test
                  UserDllLInterface.x64_CLibrary.INSTANCE.Export2();
                  System.out.println("Break13");// debug test
            }
      }
}

Lastly, the library interface is here: //UserDllLInterface.java 最后,库接口在这里://UserDllLInterface.java

import com.sun.jna.Library;
import com.sun.jna.Native;

public interface UserDllLInterface {
      public static interface CLibrary extends Library { //comes from twall's examples, thanks!
            CLibrary INSTANCE = (CLibrary) Native.loadLibrary("DllExample",CLibrary.class);
            void Export1();
            void Export2();
      }

      public static interface x64_CLibrary extends Library {
            x64_CLibrary INSTANCE = (x64_CLibrary) Native.loadLibrary
              ("x64_DllExample", x64_CLibrary.class);
           void Export1();
           void Export2();
      }
}

my C++ source that was compiled into the 32-bit and 64-bit DLLs: //x64_DllExample.dll //DllExample.dll 我的C ++源代码被编译为32位和64位DLL://x64_DllExample.dll //DllExample.dll

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h>

bool APIENTRY DllMain(HANDLE hModule, DWORD reason, LPVOID lpReserved) {
    switch(reason) {
        case DLL_PROCESS_ATTACH:
            printf("You loaded me successfully!\n");
            break;
        case DLL_PROCESS_DETACH:
            printf("You unloaded me successfully!\n");
            break;
        case DLL_THREAD_ATTACH:
            printf("You threaded me successfully!\n");
            break;
        case DLL_THREAD_DETACH:
            printf("You un threaded me successfully!\n");
            break;
    }
    return true;
}

 extern "C" __declspec(dllexport) void Export1() {
     printf("You called the function Export1\n");
 }

extern "C" __declspec(dllexport) void Export2() {
    printf("You called the function Export2\n");
}

I expected to get output something like this, with the export functions mixed in: 我希望获得类似输出的输出,其中混入了导出功能:

MIAN START
MAIN Break1
Object Created!
Break5
You loaded me successfully!
You called the function Export1
You un threaded me successfully!
Break6
You called the function Export2
You un threaded me successfully!
Break7
MAIN inter-method
Break11
You called the function Export1
You un threaded me successfully!
Break12
You called the function Export2
You un threaded me successfully!
You unloaded me successfully!
Break13
MAIN END

But instead, I get output like this (Java first, then Windows): 但是,相反,我得到了这样的输出(首先是Java,然后是Windows):

MIAN START
MAIN Break1
Object Created!
Break5
Break6
Break7
MAIN inter-method
Break11
Break12
Break13
MAIN END
You loaded me successfully!
You called the function Export1
You called the function Export2
You called the function Export1
You called the function Export2
You un threaded me successfully!
You un threaded me successfully!
You un threaded me successfully!
You un threaded me successfully!
You unloaded me successfully!

Switching to the 64-bit JVM yields similar results, with Java code going first, followed by the native library. 切换到64位JVM会产生相似的结果,首先是Java代码,然后是本机库。 I am hoping someone can help shed light on why this happens. 我希望有人可以帮助您阐明发生这种情况的原因。 Thanks in advance for any help you can provide! 预先感谢您提供的任何帮助!

printf is buffered. printf已缓冲。 If you add an fflush(stdout); 如果添加fflush(stdout); after every printf , it would output as expected. 在每个printf ,它将按预期输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM