Cannot use DLL (written in C ++) in Delphi: procedure entry point could not be found
I built the DLL in Visual Studio (C ++ source code that I hardly understand). Here is a snippet of Scraper.h :
struct SWin
{
char title[512];
HWND hwnd;
};
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
Now I am trying to use the above function in a Delphi application:
type
tWin = record
title: String;
hwnd: HWND;
end;
function ScraperGetWinList(var WinList: Array of tWin): Boolean; external 'Scraper.dll';
var
myWinList: Array [1..100] of tWin;
procedure TMainForm.GetWinListButtonClick(Sender: TObject);
begin
ScraperGetWinList(myWinList);
...
The project does not compile and I receive the following message: The entry point of the ScraperGetWinList procedure cannot be located in the dynamic link library: Scraper.dll.
What am I doing wrong?
source to share
From my experience with Linux, I would say that you are facing a " name-mangling . The entry point to your routine is not called" ScraperGetWinList ", but something like" _ZN18ScraperGetWinListEpN4SWin ".
The point is that, unlike C, in C ++ the entry point name is not the same as the function name. Not surprising: suppose you have a set of overloaded functions; they should have different entry points to your DLL. This is where the title comes into play.
The most common solution to this problem is to define the interface of your library so that it will use the C calling convention. After that, the interface functions will not be executed with the interface functions.
Note that you do not need to write the entire library in C, you only need to declare functions in order for them to call entry points of type C.
It is usually written like this:
extern "C" {
SCRAPER_API bool ScraperGetWinList(SWin winList[100]);
// More functions
}
Recompile your library and use it in Delphi without issue.
Note that you must also tweak the calling conventions (stdcall or cdecl) to match the C ++ and Delphi headers. However, this is best explained in another question.
source to share
Most likely a problem with the name mangling. The name mangling is usually done, it is C ++ code, and when writing a C ++ DLL to be used by code in another langauge, you must use the outer "C" construct, as Pavel Shved already suggested.
When using DLLs, especially when you click on other languages, you should also look at calls. I suggest you point in delphi and C ++ to use stdcall causing convstion. This is the calling convention used by the windows api as well, so it guarantees better compatibility between different compilers.
This would mean
extern "C" {
SCRAPER_API __stdcall bool ScraperGetWinList (SWin winList [100]);
}
and
ScraperGetWinList function (var WinList: tWin array): Boolean; external 'Scraper.dll';
But that's not all, the convention of calling stdcall affects the mangling name, and it turns out to be something like _ScraperGetWinList @ 4 (where 4 is the parameter size, where the array will have a pointer to the first element, so 4 bytes)
To confirm the correct characters to use, I suggest Dependency Walker ( http://www.dependencywalker.com/ ) shows that it is the function names that are exported by the DLL. After confirming the name "_ScraperGetWinList @ 4", add it to delpgi as follows:
ScraperGetWinList function (var WinList: tWin array): Boolean; external 'Scraper.dll' name '_ScraperGetWinList @ 4';
source to share
Did you actually export the entry point function to C ++ code? This actually got in the way of me the first time I compiled a C ++ dll in Visual Studio for use in a dotnet application.
For example, I needed to expose a print driver in unmanaged code so that some other developers could access it in VB.net. This is what I did.
In foo.cpp:
extern "c" {
___declspec(dllexport) bool FooBar()
{
// Call some code on my cpp objects to implement foobar
}
}
Then, in a file called foo.def:
LIBRARY "mylib"
EXPORTS
FooBar
AnyOtherFunctionsItExports
This is how I got it working. I may not be doing my best. I have a little bit of C ++ experience and also mostly don't work on windows.
source to share