0

背景优先,问题以粗体显示:

我是一名学生,对于一个暑期研究项目,我将编写一个 Java 程序,它可以让我将从研究硬件收集的数据导出到 Windows 环境中的 MATLAB 中——我不需要该程序可以移植到其他平台。我有一个包含 C/C++ 声明的优秀 API 的第三方 DLL,但我无权访问 DLL 的源代码。

我只知道 Java,所以在查看了可用选项后,我决定使用 JNA,因为它看起来最简单易用,而且 JNA 目前还在维护。我请一个知道 C++ 的朋友为我制作了一个示例 DLL,这样我就可以从底部开始,对加载库和使用 JNA 访问本机方法进行“hello world”风格的测试。我遵循了这里的示例——并阅读了 twall 和/或 technomage 对其他人问题的一百个回复。

由于 jna.library.path 以null开头,解决了一些 UnsatisfiedLinkErrors 问题后,我将提供给我的 32 位示例 DLL 重新编译为 64 位,并将它们都放入 /bin 文件夹中,然后让程序确定哪一个访问,取决于运行的JVM。我知道我无法使用我的 32 位第三方 DLL 执行此操作,但这只是我概念验证阶段的一部分。

我已经能够很容易地访问 DLL 方法,但是我看到输出——所有打印语句——以意想不到的顺序出现。看起来是我的 Java 代码从头到尾执行,然后本机库从头到尾执行

在我的项目后期,我需要调用原生函数,然后是 java 方法,然后是原生函数,所以我需要尽早了解是什么导致了这个奇怪的序列。一开始我尝试了一种非常程序化的方法;下面是我尝试将这些方法打扮成我可以操作的对象,这产生了相同的结果。我猜这与 JVM 和房子的本机端如何交互,或者 Windows 和 Java 处理 I/O 方式的差异有关,但我很难理解是什么原因造成的,或者如何解决这个问题.

我的设置如下所示: // 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
    }
}

我调用库的方法在这里: // 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
            }
      }
}

最后,库接口在这里: //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();
      }
}

我编译成 32 位和 64 位 DLL 的 C++ 源代码://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");
}

我希望得到这样的输出,其中混合了导出功能:

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

但相反,我得到这样的输出(首先是 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!

切换到 64 位 JVM 会产生类似的结果,首先是 Java 代码,然后是本机库。我希望有人可以帮助阐明为什么会发生这种情况。提前感谢您提供的任何帮助!

4

1 回答 1

0

printf被缓冲。如果fflush(stdout);在 every 之后添加一个printf,它将按预期输出。

于 2013-05-24T16:38:46.553 回答