[SOLVED] Issue Trying to Call Windows C DLL from Lazarus lazarus / 34-Windows ---------------------------------------------------------------------- kevin.black · 2013-03-12 10:03 Hi, If this is a bit long-winded, I apologise.  It has taken up a lot of time with no result. We can call a functions from a Windows System DLL from LAZARUS.  We can call our DLL functions from a C# application.  Here is the relevant info from the C header file:and the C# application. .h File details: CLASS_DECLSPEC int STDCALL emp_login(char* keypath, char* password) ; .cc file details: int main(int argc, char** argv) {     int sessionID = emp_login("C:\\path\\to\\keyfile.p12", "password"); So the function has two Char* arguments, but accepts two strings (I assume the C# compiler does this - I'm no C/C# expert) So I have tried everything(sic) in LAZARUS including arguments of string, ansistring,pchar,char,pansistring and, whilst the all build, as soon as the applcation runs the red run light appears then within half a second disappears.  If I comment out the call to the function (regardless of how it is declared, the application works. Here are the code snippits from LAZARUS: function emp_login(Path: pChar; password: pChar): integer; stdcall;   external 'libEmpyreanCrypto.dll'; The routine: procedure TEmpyreanMainFrm.btnTestClick(Sender: TObject); var   sessionID: integer;   Result: empErrCode;   MsgTitle: string;   MsgMessage: string;   LibHandle: THandle;   Location: string;   Password: string;   ptrLocation: PChar;   ptrPassword: PChar; begin   showmessage ('Start');   try     Location := 'c:\Test';     Password := '123';     ptrLocation := @Location;     ptrPassword := @Password;     sessionID := emp_login(ptrLocation, ptrPassword);   except     on E: Exception do       ShowMessage(E.ClassName + ' error raised, with message : ' + E.Message);   end; So this looked fairly straight forward.  If the call to emp_login is commented out the program runs.  If it is left in the program compiles and builds, but the program runs (ie. the red indicator lights up for haf a second) and stops.  The program never progresses past that point. Does any one have any ideas, ie. what is the correct declaration and what is the correct calling syntax.  I've searched wherever I can, but cannot find anything reasonable. Thanks, Kevin ---------------------------------------------------------------------- BigChimp · 2013-03-12 10:14 1. Please specify LAZARUS/FPC/OS version, see my signature 2. FPC (and therefore Lazarus) cannot call C#/.Net dlls, only C dlls. Please make sure you're talking about C dlls. 2a Lazarus can use ActiveX dlls, I vaguely seem to recall C# can create these... This might be an avenue to explore if C# is a requirement. 3. The calling conventions (cdecl etc) are described in the FPC documentation (Programmer's Guide, chapter 7) 4. You can look here regarding variable declarations: http://wiki.lazarus.freepascal.org/Pascal_for_C_users 5. Please wrap your code in code tags (the # mark in the editor toolbar). Makes it easier to copy/paste/inspect ---------------------------------------------------------------------- marcov · 2013-03-12 10:28 Your main mistake is here: Quote from: kevin.black on March 12, 2013, 11:03:00 am Code: [Select]    ptrLocation := @Location;     ptrPassword := @Password; Ansistrings are already references. So you pass here a pointer to a pointer. Simply typecast location to pchar; pchar(location), pchar(password) in the function call ---------------------------------------------------------------------- kevin.black · 2013-03-12 22:17 @BigChimp, Thank you and OK: Lazarus V1.1 FPC V2.7.1 x86_64-win64-win32/win64 Windows 7 Professional VMWare Workstation v9.0 x64 VM, with 4Gb RAM assigned (I do not think thi is an issue because it can access functions from a Windows DLL) It is runniig on an Intel i7 Box which in itself is running Server 2008 R2 Widgit Set Win32/64 I also used the CodeTyphon install which gives me additional components, but not relevant here I think, because I'm just testing the DLL call.  I have reviewed the documentation and there is nothing there that I can see that I haven't done/tried.  I am double/triple checking with the developer of the DLL that it is plain old C.  It is strange though that I can call functions from a Windows System DLL and it works, but not here. Code: [Select]CLASS_DECLSPEC int STDCALL emp_login(char* keypath, char* password) ; I assume this from the C means that I should use stdcall, but I have tried it with cdecl and same result. @Marcov Code: [Select]  Location: string;   Password: string; begin   showmessage ('Start');   try     Location := 'c:\Test';     Password := '123';     sessionID := emp_login(pChar(Location), pChar(Password)); Well, tried that, and to no avail, exactly same result - the red I'm running light blinks on and then off never gets to display anything.  If I comment out the line: Code: [Select]//sessionID := emp_login(pChar(Location), pChar(Password)); the code runs fine? Again, and other than the origins of the DLL (ie. is it C, C#, C++ or .net which I am further investigating) I cannot think of much I and the chap I'm working with haven't tried. Any other suggestions greatly appreciated. EDIT/UPDATE I have since learned from the original DLL developer that the DLL was compiled with a C++ compiler in NETBEANS.  He is, at my request, doing a build of a DLL using bog standard, plain old C.  He will have the same functions/calling setup as in the C++ DLL (but without the underlying code).  If this works then it is the C++ build. Guys, can you confirm that Lazarus cannot handle a DLL built with a C++ compiler?  I am unsure how much effort will be required to 'convert' the DLL from C++ to C if this is the reason for it not working (and I really don't want to do our application development in C# which is where I'm being pushed)...... Thanks, Kevin ---------------------------------------------------------------------- BigChimp · 2013-03-13 06:09 Thanks for the extensive version info Good, you're on the bleeding edge regarding FPC which at least means you're not missing any features/improvements. No, FPC cannot handle C++ DLLs. There has been an effort to provide that functionality but it's too basic IIUC. Something like SWIG may be useful (it creates wrapper files for C++ code, much like h2pas does for C libraries), but an Object Pascal port is still experimental: https://bitbucket.org/reiniero/smalltools/src, directory SWIG Note: a C# dll is the same as a .Net dll is the same as a VB.Net dll... all .Net languages compile to the .Net runtime/intermediate language. Windows system dlls are c, not c++. That's why you can call them. Finally, I've added some links to the wiki article I posted earlier to other pages of interest (using h2pas to semi-automatically convert c libraries). Please see the links under See Also. Thanks. ---------------------------------------------------------------------- kevin.black · 2013-03-13 12:29 @BigChimp, Thanks for that, a couple of comments below: QuoteNo, FPC cannot handle C++ DLLs. There has been an effort to provide that functionality but it's too basic IIUC. It looks like it might in my case.  I am told (I cannot verify, but the programmer assures me)  that the DLL I am using was compiled using the NETBEANS C++ Compiler and I can talk to it.  The function calls were setup using STDCALL The issue was not, as it turns out because of the DLL compiler, although I am sure I cannot talk to a C#/.Net compiled DLL.  The issue was a mismatch of 64bit application, calling a 32bit DLL.  So the DLL was compiled using the 32bit C++ NETBEANS compiler and, when I recompiled my application (now a simple TEST application) as a 32bit app it worked fine, see code below: Code: [Select]Implementation {Calls to EncFs DLL} function emp_login(Path: pChar; password: pChar): integer; stdcall; external 'libEmpyreanCrypto'; {$R *.lfm} { TfrmDLLTest } procedure TfrmDLLTest.BitBtn1Click(Sender: TObject);  var   X: integer;   Location: string;   Password: string; begin   showmessage ('Start');   try     Location := 'Test';     Password := '123';     X := emp_login(pChar(Location), pChar(Password));     showmessage('the value of SessionID is: ' + inttostr(X));   except     on E: Exception do       ShowMessage(E.ClassName + ' error raised, with message : ' + E.Message);   end; end; That's why the Windows System DLL worked (as well as it is a C DLL) it was also a 64bit DLL so my 64bit app had no problem using it. Thank you for following up and keeping tabs on this issue, your knowledge and insight is appreciated. Regards, Kevin ---------------------------------------------------------------------- BigChimp · 2013-03-13 12:37 Heh, glad it works.... though I'm sure a C++ compiler can compile C code just fine (Apart from that, as I said, there is some support for calling C++ dlls in FPC, and you seem to be calling a regular function - nothing to do with objects, so perhaps that's why it works even if it is a C++ dll. But I'll stop speculating and leave it to the experts... Marco are you there?)