I'm trying to compile a C ++ program that wants to read the ports in the registry. The C ++ expert is small, I'm Java, and this is the JNI class for working with Java. Already enraged, I do not understand what he wants:

cl -I "% JAVA_HOME% \ include" -I "% JAVA_HOME% \ include \ win32" myJniClass.cpp / link / DLL Microsoft (R) C / C ++ Optimizing Compiler Version 19.00.24210 for x64 Copyright (C) Microsoft Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 14.00.24210.0 Copyright (C) Microsoft Corporation. All rights reserved. /out:myJniClass.dll /dll /implib:myJniClass.lib /DLL myJniClass.obj Creating library myJniClass.lib and object myJniClass.exp myJniClass.obj : error LNK2019: unresolved external symbol __imp_RegEnumValueA referenced in function Java_serialport_Serial_getSerialPortNames myJniClass.obj : error LNK2019: unresolved external symbol __imp_RegOpenKeyExA referenced in function Java_serialport_Serial_getSerialPortNames myJniClass.dll : fatal error LNK1120: 2 unresolved externals 

To compile, I downloaded Visual C++ Build Tools and launched Visual C++ 2015 x64 Native Build Tools Command Prompt . The source itself is verified, without errors. The code is successfully compiled via Android Studio + NDK.

Here is the problem code snippet:

 HKEY phkResult; LPCSTR lpSubKey = "HARDWARE\\DEVICEMAP\\SERIALCOMM\\"; jobjectArray returnArray = NULL; //if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &phkResult) == ERROR_SUCCESS){ if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &phkResult) == ERROR_SUCCESS){ boolean hasMoreElements = true; DWORD keysCount = 0; char valueName[256]; DWORD valueNameSize; DWORD enumResult; while(hasMoreElements){ valueNameSize = 256; //enumResult = RegEnumValueA(phkResult, keysCount, valueName, &valueNameSize, NULL, NULL, NULL, NULL); enumResult = RegEnumValue(phkResult, keysCount, valueName, &valueNameSize, NULL, NULL, NULL, NULL); if(enumResult == ERROR_SUCCESS){ keysCount++; } else if(enumResult == ERROR_NO_MORE_ITEMS){ hasMoreElements = false; } else { hasMoreElements = false; } } 

Specifically, the RegEnumValueA function is RegEnumValueA , and, apparently by mistake, it has become __imp_RegOpenKeyExA . This prefix comes in generated .lib and .obj. For example:

 e __imp_PurgeComm __imp_SetCommBreak __imp_SetCommMask __imp_SetCommState __imp_SetCommTimeouts __imp_WaitCommEvent __imp_RegEnumValueA __imp_RegOpenKeyExA 

2 answers 2

Try it out if adding the directive will save you

 #pragma comment(lib,"Advapi32") 

which suggests that the Advapi32 library should be included in the project, in which, in fact, is your function.

  • Thank. I will try and accomplish your goal. - Eugene
  • Does it matter what you need to use - Visual Studio, SDK, Visual Studio Build Tools, Visual C ++ Build Tools? I installed only "Microsoft Visual C ++ Build Tools 2015 Update 3". - Eugene
  • Visual C ++ accurately understands this pragma. It is possible and as advised @Mikhajlo - it is important that you need to explicitly connect this library. - Harry
  • Wow It really helped! I chose this answer as the best, since it is simpler from the point of view of compilation, more self-sufficient. But I don’t understand why the MinGW compiler and Android NDK didn’t find it without a pragma. and why he did not find him with a gun. - Eugene

You can simply add to your command line after the .cpp file

 advapi32.lib 

or the same after /link .

  • Thank. I will try and accomplish your goal. - Eugene