【发布时间】:2018-04-25 19:18:08
【问题描述】:
我正在尝试在 cpp 程序中获取 Windows 用户名,然后使用 Java 本机接口 (JNI) 从 Java 代码中调用该程序来进行概念验证。现在我所拥有的是一个示例 JNI hello world 程序,它能够编译和打印 Hello world 或我设置的任何参数。现在在一个单独的 cpp sn-p 中,我能够获取当前用户名并且它也可以工作;如下所示:
#include <iostream>
#include <windows.h>
using namespace std;
int main()
{
char acUserName[100];
DWORD nUserName = sizeof(acUserName);
if (GetUserName(acUserName, &nUserName)) {
cout << "User name is " << acUserName << "." << endl;
cin.get();
}
return 0;
}
在命令提示符下使用我的 G++ 编译和执行时,它会正确打印当前用户名。
现在我只想将这两个程序结合起来。当我这样做时,如下所示
public class Sample1
{
public native String fetchCurrentUserName();
public static void main(String[] args)
{
System.loadLibrary("Sample1");
Sample1 sample = new Sample1();
String userName = sample.fetchCurrentUserName();
System.out.println("userName: " + userName);
}
}
这是java部分,cpp部分如下:
#include "Sample1.h"
#include <string.h>
#include <iostream>
#include <windows.h>
using namespace std;
JNIEXPORT jstring JNICALL Java_Sample1_fetchCurrentUserName
(JNIEnv *env, jobject obj) {
char acUserName[100];
DWORD nUserName = sizeof(acUserName);
if (GetUserName(acUserName, &nUserName)) {
cout << "User name is " << acUserName << "." << endl;
cin.get();
}
const char* userName = acUserName;
//const char* userName = "acUserName";
return env->NewStringUTF(userName);
}
void main(){}
这不再编译了,它说
Sample1.obj : error LNK2019: unresolved external symbol __imp_GetUserNameA referenced in function Java_Sample1_fetchCurrentUserName
Sample1.dll : fatal error LNK1120: 1 unresolved externals
我使用以下命令编译 JNI 代码。
cl -I"C:\Program Files\Java\jdk1.8.0_131\include" -I"C:\Program Files\Java\jdk1.8.0_131\include\win32" -LD Sample1.cpp -FeSample1。 dll
根据https://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html 的教程。现在从堆栈溢出中的其他几个问题来看,我的程序似乎无法以某种方式链接 Windows 库或领导者。但我不知道如何解决这个问题。任何机构有什么好主意吗?请让我开心!感谢您抽出宝贵时间:D 我查看了Linking of dll file in JNI,这与我的问题非常相关。但不确定这些解决方案是否适用于我。
编辑
error: LNK1120: 5 unresolved externals 这个问题有类似的问题,它似乎有与 Remy 建议的与 Advapi32.lib 链接的相同解决方案。至少现在我学到了一些新东西,比如#pragma cmets 和 Advapi32 库的作用。非常感谢!
【问题讨论】:
-
您的 C++ 代码需要链接到
Advapi32.lib,要么通过项目选项中的链接器参数,要么通过 C++ 代码本身中的#pragma comment(lib)语句。否则,您可以使用 Win32 APILoadLibrary()和GetProcAddress()函数在运行时直接从Advapi32.dll获取指向GetUserNameA()的指针,而不是在编译时链接到Advapi32.lib -
另一方面,为什么在 C++ 中使用
GetUserName()? Java 对用户名有自己的访问权限:Get login username in java -
我在其他问题中看到了这个解决方案。但是我自己不知道这个 Advapi32.lib 做了什么。你能告诉我为什么这对我来说很重要,我在哪里可以找到执行任务的确切命令/代码。我是 cpp 和 JNI 的超级菜鸟,都很抱歉。 :(
-
这与JNI无关。这就是 C++ 编译器\链接器的一般工作方式。
Advapi32.lib是Advapi32.dll的导入库,它告诉链接器从 DLL 导出哪些函数以及如何导出。链接器使用导入库来解析 C++ 代码进行的 DLL 函数调用。 -
我给你贴了更详细的答案
标签: java c++ winapi java-native-interface