1

好的。我一直在尝试使我用 Java 编写的程序能够通过使用 JNI 来确定 Windows 桌面是否被锁定。我已经成功地让 JNI 工作了,但是我最初使用的 C 代码没有返回正确的答案。我得到了一些新代码(从这里开始),稍微修改了一下,但是我遇到了链接错误。

链接时,我得到两个未定义的引用,一个指向 OpenInputDesktop,一个指向 CloseDesktop。这些都是 user32.dll 的一部分。

我用来链接和创建我的 DLL 的命令是:

c:/MinGW/bin/gcc -shared -o JNIHelper.dll
                  com_little_cute_display_helper_JNIHelper.o
                  -Wl,--add-stdcall-alias,--kill-at,--output-def,def_file

我已经尝试显式添加 lib 目录以及库,但错误是相同的。这并不奇怪,因为 MinGW 将我的命令扩展到:

 c:/MinGW/bin/../libexec/gcc/mingw32/3.4.5/collect2.exe --shared -Bdynamic
           -e _DllMainCRTStartup@12 --enable-auto-image-base -o JNIHelper.dll
           /mingw/lib/dllcrt2.o c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/crtbegin.o
           -Lc:/MinGW/bin/../lib/gcc/mingw32/3.4.5
           -Lc:/MinGW/bin/../lib/gcc -L/mingw/lib/gcc/mingw32/3.4.5
           -Lc:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../../../mingw32/lib
           -L/mingw/lib/gcc/mingw32/3.4.5/../../../../mingw32/lib
           -L/mingw/lib -Lc:/MinGW/bin/../lib/gcc/mingw32/3.4.5/../../..
           -L/mingw/lib/gcc/mingw32/3.4.5/../../.. 
           com_little_cute_display_helper_JNIHelper.o
           --add-stdcall-alias --kill-at --output-def def_file
           -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32
           -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt
           c:/MinGW/bin/../lib/gcc/mingw32/3.4.5/crtend.o

因此,如果您阅读所有这些混乱,您会看到 c:/MinGW/lib (保存 libuser32.a 的位置)和 -luser32 都已经在那里了。基本上,这应该可以正常链接。

这是我之前使用的相同命令,只是没有 -lwtsapi32(因为我使用的是终端服务 API),然后它运行良好,并且能够找到它需要的库。

现在我在代码中所做的更改(dan_g 的回答)是取出静态变量,因为我使用的是 XP 并且不需要担心 Win9x 兼容性。当我按原样使用他的代码时,我遇到了同样的基本错误,例如,无法链接到 GetProcAddress,即使它已经在链接器命令中的 kernel32 中。

我在想我错过了一些魔法命令。标准 Win32API 中的函数似乎不想链接。自从我使用 C 和 MinGW 已经好几年了。我正在做很多我以前没有做过的事情。

有人可以指出我正确的方向吗?


好的,我一直在努力解决这个问题,但我仍然卡住了。如果我将源代码做成一个简单的小 C 程序(没有 JNI 的东西),它看起来像这样:

#define _WIN32_WINNT 0x0501
#define WINVER 0x0501
#include <windows.h>
#include <windef.h>
#include <winnt.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) {

    HDESK hDesk = OpenInputDesktop(0, FALSE, MAXIMUM_ALLOWED);

    if (hDesk) {
        CloseDesktop(hDesk);

        printf("unlocked");
    } else {
        printf("locked");
    }
}

MinGW 将愉快地编译和链接它,并且可执行文件运行。如果我使用我一直在使用的命令(更改为反映此文件),它会生成一个没有问题的 DLL。

4

1 回答 1

2

我已经弄清楚了问题所在。当我编译我的代码以放入供 JNI 使用的 Java 的 DLL 时,当我使用 nm 查看目标文件中的内容时,目标文件具有以下两个列表:

     U _CloseDesktop
     U _OpenInputDesktop

当需要链接时,找不到那些,所以我得到链接器错误。当我将没有所有 JNI 内容的代码编译为 DLL(显然不适用于 Java)时,符号如下所示:

     U _CloseDesktop@4
     U _OpenInputDesktop@12

如您所见,在编译生成 JNI DLL 时,我的函数没有被 @n 修饰,这就是导致我的链接错误的原因。有谁知道我该如何解决这个问题?

那么问题出在哪里?

我不包括 windows.h

这让一切变得不同。也许这会帮助别人。

于 2009-08-12T20:10:37.190 回答