Page 1 of 1

Underscore in application

PostPosted: Mon Jan 29, 2018 6:35 am
by denville
Still maintaining CPB6 I'm afraid..

I have a third party library; I have created a compatible .lib using implib, and I have used the library successfully in countless BCB6 console applications.

I want to use this library in a VCL application but linking fails; undefined _functions (ie with leading underscore). Now when I build the Console app, provided I #include <windows.h>, everything is perfect. I discovered that if I leave out windows.h then I get the same problem as the VCL attempt. If I try to include windows.h in the VCL app as a work-around, it doesn't fix the problem.

I have looked at windows.h but it is very convoluted, I wonder if anyone can tell me what it is that it does in the Console app to fix the problem, an why it doesn't do it in the VCL app ?

Thanks.

Re: Underscore in application

PostPosted: Mon Jan 29, 2018 11:03 am
by 2ffat
*IF* I remember correctly from my coding days in C++Builder 6, function name with leading underscores were reserved for the Builder VCL system files. Using them in your functions was verboten as they could cause conflicts. You may have rename your functions.

I suspect someone with better memory will correct me.

Re: Underscore in application

PostPosted: Mon Jan 29, 2018 1:06 pm
by rlebeau
denville wrote:Still maintaining CPB6 I'm afraid..


So am I.

denville wrote:I want to use this library in a VCL application but linking fails; undefined _functions (ie with leading underscore).


Such as? There is no difference in linking a .lib file to a console app vs a GUI app. So something else is going on.

denville wrote:Now when I build the Console app, provided I #include <windows.h>, everything is perfect. I discovered that if I leave out windows.h then I get the same problem as the VCL attempt.


What are the EXACT errors? Windows.h only affects the compiler, not the linker.

denville wrote:If I try to include windows.h in the VCL app as a work-around, it doesn't fix the problem.


The VCL is intimately tied to the Win32 API, so it already includes windows.h whether you want it or not.

denville wrote:I wonder if anyone can tell me what it is that it does in the Console app to fix the problem, an why it doesn't do it in the VCL app ?


It does nothing, because it is not the one fixing your issue. Something else is going on. But I can't answer what that something is without more details.

Re: Underscore in application

PostPosted: Mon Jan 29, 2018 1:11 pm
by rlebeau
2ffat wrote:*IF* I remember correctly from my coding days in C++Builder 6, function name with leading underscores were reserved for the Builder VCL system files. Using them in your functions was verboten as they could cause conflicts. You may have rename your functions.


You are thinking of system functions in the Delphi RTL. In a DLL, an exported function name is prefixed with an underscore if the function uses either the __stdcall calling convention, or the __cdecl calling convention without C language linkage, and if the DLL was not compiled with a .def file to export different names than the compiler's default naming conventions.

Re: Underscore in application

PostPosted: Tue Jan 30, 2018 5:29 am
by 2ffat
Like I said, it's been awhile...

Re: Underscore in application

PostPosted: Wed Jan 31, 2018 12:26 pm
by denville
So - this builds and runs fine and is indicative of previous (more meaningful!) successful projects:
(New | Console Wizard |C++ | Console Application)

#pragma hdrstop
//---------------------------------------------------------------------------
#include <windows.h>

#include "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\include\ipworks.h"
#pragma comment(lib, "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\ipworks_bor.lib")
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
XML xml; // XML is IPWorks class from the lib

return 0;
}
//---------------------------------------------------------------------------

Comment out windows.h:

#pragma hdrstop
//---------------------------------------------------------------------------
//#include <windows.h>

#include "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\include\ipworks.h"
#pragma comment(lib, "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\ipworks_bor.lib")
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
XML xml; // XML is IPWorks class from the lib

return 0;
}
//---------------------------------------------------------------------------
Linker Error] Unresolved external '_IPWorks_XML_Destroy' referenced from C:\BCB6\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
[Linker Error] Unresolved external '_IPWorks_XML_Create' referenced from C:\BCB6\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
(Note _underscore)

Put back windows.h, comment out the lib link to see what it's successfully finding in the lib:

#pragma hdrstop
//---------------------------------------------------------------------------
#include <windows.h>

#include "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\include\ipworks.h"
//#pragma comment(lib, "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\ipworks_bor.lib")
//---------------------------------------------------------------------------
#pragma argsused
int main(int argc, char* argv[])
{
XML xml; // XML is IPWorks class from the lib

return 0;
}
//---------------------------------------------------------------------------
[Linker Error] Unresolved external 'IPWorks_XML_Destroy' referenced from C:\BCB6\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
[Linker Error] Unresolved external 'IPWorks_XML_Create' referenced from C:\BCB6\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
(note no underscore)

VCL app:
#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
#include "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\include\ipworks.h"
#pragma comment(lib, "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\ipworks_bor.lib")

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
XML xml; // XML is IPWorks class from the lib

}
//---------------------------------------------------------------------------
[Linker Error] Unresolved external '_IPWorks_XML_Destroy' referenced from C:\LINUX-IPWORKS\IPWORKS-16.0\MY-DEV\BCB6\XML_1\UNIT1.OBJ
[Linker Error] Unresolved external '_IPWorks_XML_Create' referenced from C:\LINUX-IPWORKS\IPWORKS-16.0\MY-DEV\BCB6\XML_1\UNIT1.OBJ
(note _underscore)

Put in windows.h - no difference, same errors.

Re: Underscore in application

PostPosted: Wed Jan 31, 2018 7:08 pm
by rlebeau
denville wrote:
Code: Select all
#include "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\include\ipworks.h"
#pragma comment(lib, "C:\TFS_ES\CPP\IpWorks\IpWorks\win-lib-32\ipworks_bor.lib")



You shoudn't be using absolute paths like that. Put the base paths in the Project options, and then use relative paths in the code.

denville wrote:Comment out windows.h:
...
[Linker Error] Unresolved external '_IPWorks_XML_Destroy' referenced from C:\BCB6\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
[Linker Error] Unresolved external '_IPWorks_XML_Create' referenced from C:\BCB6\BORLAND\CBUILDER6\PROJECTS\UNIT1.OBJ
(Note _underscore)


How EXACTLY are those functions defined in ipworks.h? The only possibility that comes to mind is if the functions in question are declaring their calling convention using a precompiler macro in such a way that it is dependent on something that windows.h defines, causing the code to compile using one calling convention (like __stdcall) when windows.h is included, and a different calling convention (like __cdecl) when omitted.

denville wrote:VCL app:


VCL apps always include windows.h, whether you include it in your own code or not.

If you really want to know what's going on, I suggest you invoke the IDE's preprocessor (Project Manager > right-click a .cpp file > choose "Preprocess". Or run CPP32.EXE directly) on your code so you can see exactly how preprocessor macros are being expanded, and you can see exactly what the compiler sees. I'm sure you will then notice some differences.

Re: Underscore in application

PostPosted: Fri Feb 02, 2018 3:16 pm
by denville
Exactly right as usual.

I can see now that the calling convention is modified depending on whether WIN32 is defined. Defining it myself in the project has the magic effect. Mind you, I couldn't see where WIN32 got defined by default in the console apps that worked.

Thanks !

Re: Underscore in application

PostPosted: Mon Feb 05, 2018 2:21 pm
by rlebeau
denville wrote:Mind you, I couldn't see where WIN32 got defined by default in the console apps that worked.


The WINAPI macro, and other related macros, are defined in windef.h (which is included by windows.h):

Code: Select all
#ifdef _MAC
#define CALLBACK    PASCAL
#define WINAPI      CDECL
#define WINAPIV     CDECL
#define APIENTRY    WINAPI
#define APIPRIVATE  CDECL
#ifdef _68K_
#define PASCAL      __pascal
#else
#define PASCAL
#endif
#elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED)
#define CALLBACK    __stdcall
#define WINAPI      __stdcall
#define WINAPIV     __cdecl
#define APIENTRY    WINAPI
#define APIPRIVATE  __stdcall
#define PASCAL      __stdcall
#else
#define CALLBACK
#define WINAPI
#define WINAPIV
#define APIENTRY    WINAPI
#define APIPRIVATE
#define PASCAL      pascal
#endif