We are implementing a one-to-one mapping of some winapi
methods, for the xidobi serial port project. The mapping of the C
methods to java works as expected, but for an unknown reason GetLastError()
get cleared.
Here is the C-Code:
// 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();
}
In Java we call the mapped native methods in like this:
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)
We figured out that if we call GetLastError()
in C right after CreateFile(..)
the correct error code is returned. Since the one-to-one mapping is dead simple we assume that JNI or the VM calls SetLastError()
itself and clears our last error.
We don't want to give up the one-to-one mapping design, so what can we do to solve this puzzle?
Here is a similar question that doesn't help in this case: CreateFile() returns INVALID_HANDLE_VALUE but GetLastError() is ERROR_SUCCESS