gpt4 book ai didi

java - 如何防止 JNI 覆盖 GetLastError()

转载 作者:行者123 更新时间:2023-11-30 07:19:49 24 4
gpt4 key购买 nike

我们正在为 xidobi 实现一些 winapi 方法的一对一映射。串口项目。 C 方法到 java 的映射按预期工作,但由于未知原因 GetLastError() 被清除。

这是C代码:

// CreateFile ////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL
Java_org_xidobi_OS_CreateFile(JNIEnv *env, jobject this,
jstring lpFileName,
jint dwDesiredAccess,
jint dwShareMode,
jint lpSecurityAttributes,
jint dwCreationDisposition,
jint dwFlagsAndAttributes,
jint hTemplateFile) {

const char* fileName = (*env)->GetStringUTFChars(env, lpFileName, NULL);

HANDLE handle = CreateFile(fileName,
dwDesiredAccess,
dwShareMode,
(LPSECURITY_ATTRIBUTES) lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
(HANDLE) hTemplateFile);

(*env)->ReleaseStringUTFChars(env, lpFileName, fileName);

return (jint) handle;
}

// GetLastError ////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL
Java_org_xidobi_OS_GetLastError(JNIEnv *env, jobject this) {
return (jint) GetLastError();
}

Java 中,我们这样调用映射的 native 方法:

int handle = os.CreateFile("\\\\.\\" + portName, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

if (handle != INVALID_HANDLE_VALUE)
return handle;
int lastError= os.GetLastError(); //-> sometimes 0 (ERROR_SUCCESS)

我们发现,如果我们在 CreateFile(..) 之后立即在 C 中调用 GetLastError(),则会返回正确的错误代码。由于一对一映射非常简单,我们假设 JNI 或 VM 自行调用 SetLastError() 并清除我们的最后一个错误。

我们不想放弃一对一的映射设计,那么我们可以做些什么来解决这个难题呢?

这是一个类似的问题,但在这种情况下没有帮助:CreateFile() returns INVALID_HANDLE_VALUE but GetLastError() is ERROR_SUCCESS

最佳答案

无法保证 GetLastError() 在您对 CreateFile 的 native 调用和对 GetLastError。因此,您应该在 CreateFile 之后立即调用 GetLastError 并将值保存在您自己的线程本地槽中。

然后您的 GetLastError 实现将从您存储它的任何地方检索它。

您可能希望将其重命名为 LastXidobiError 或其他名称,因为它只会检索由您的库中的调用设置的错误。

// Space to store last error ////////////////////////////////////////////
static DWORD dwTlsIndexLastError = 0;

BOOL WINAPI DllMain(
_In_ HINSTANCE hinstDLL,
_In_ DWORD fdwReason,
_In_ LPVOID lpvReserved
){


switch(fdwReason){
case DLL_PROCESS_ATTACH:
dwTlsIndexLastError = TlsAlloc();
break;
case DLL_PROCESS_DETACH:
TlsFree(dwTlsIndexLastError);
dwTlsIndexLastError = 0;
break;
}
return TRUE;
}

///// Save the last error.
///// Call this function after the "real" function whose error you want to report.
void SaveLastError()
{
TlsSetValue(dsTlsIndexLastError, (LPVOID)(DWORD_PTR)GetLastError());
}
// GetLastError ////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL
Java_org_xidobi_OS_GetLastError(JNIEnv *env, jobject this) {
return (jint) TlsGetValue(dsTlsIndexLastError);
}

// CreateFile ////////////////////////////////////////////////////////////
JNIEXPORT jint JNICALL
Java_org_xidobi_OS_CreateFile(JNIEnv *env, jobject this,
jstring lpFileName,
jint dwDesiredAccess,
jint dwShareMode,
jint lpSecurityAttributes,
jint dwCreationDisposition,
jint dwFlagsAndAttributes,
jint hTemplateFile) {

const char* fileName = (*env)->GetStringUTFChars(env, lpFileName, NULL);

HANDLE handle = CreateFile(fileName,
dwDesiredAccess,
dwShareMode,
(LPSECURITY_ATTRIBUTES) lpSecurityAttributes,
dwCreationDisposition,
dwFlagsAndAttributes,
(HANDLE) hTemplateFile);

// Save the value of GetLastError for the relevant function
SaveLastError();

(*env)->ReleaseStringUTFChars(env, lpFileName, fileName);

return (jint) handle;
}

关于java - 如何防止 JNI 覆盖 GetLastError(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14396877/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com