[SOLVED] Call to a C dll function used to work with old FPC lazarus / 64-FPC development ---------------------------------------------------------------------- avra · 2020-08-28 08:32 I have some very old code that could successfully call a function in C dll, and I have old executable that confirms that compiled application still works on my current system where dll is. However, that application doesn't work when the same project is compiled with FPC 3.2.1 and Lazarus 2.0.11. Well, it works if I do not use just one single function from that dll. Using that single function causes 'External: SIGSEGV' exception at address 655065E2. Both old and new IDE and DLL are 32bit, problem shows also without running code from IDE, clean up and build all did not help, switching off all optimization did not help, current testing OS is Win10x64, and all tested functions from dll wrapper work fine except that one. This is pascal wrapper for the problematic function: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i function pilg_getconnectedserver(servernamebuf: pchar; var bufsize: longint; var NodeID: longint; var port: longint; seq: longint): longint; stdcall; external 'pilog32.dll'; and this is what it looks in C: Code: C  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i EXPORTPIINT32 pilg_getconnectedserver(   char PIPTR* lpszServerNameBuf, // server name buffer   int32 PIPTR* plBufSize, // buffer size - in/out   int32 PIPTR* plNodeId, // node id    int32 PIPTR* plPort,   // port number   int32  lSeq  // sequence GETFIRST, GETNEXT);with some more details here: https://techsupport.osisoft.com/Documentation/PI-SDK/PI- API/Functions/pilg_getconnectedserver.htm. That function worked well when compiled with old FPC SVN 05-07-2013 Rev 25050 and Lazarus SVN 05-07-2013 Rev 42002. It also works well when compiled with even older IDE from 2010. Since that single function is kind of important detail (there is no other way to get the list of connected servers), I will try to fix the problem since I have to revisit the project. I have some ideas which I do not like too much, so before digging deeper I am asking for your suggestions in a hope to hear something that could help me. All comments are welcome, and at this stage I am open to all ideas. ---------------------------------------------------------------------- 440bx · 2020-08-28 09:07 To solve the problem you describe, I would compile the program that calls the DLL with a previous version of FPC (v3.0.4 for instance) and ask for an assembly listing.  I'd do the same with FPC v3.2.1 and compare the code that is generated by each compiler.  If it works with one and not the other, there is probably a bug in the compiler and examining the assembly listing (dll function call) will likely indicate what the problem is. Also, you could trace through the DLL function and find out the instruction that causes SIGSEV and why.  That would very helpful in figuring out what is causing the problem. HTH. ---------------------------------------------------------------------- Thaddy · 2020-08-28 09:07 Are you sure it is stdcall? Because portable API's often default to cdecl on all platforms including Windows. First thing I would do is test with cdecl. I can't find any macro for stdcall. Another thing that comes to mind is that since 3.2.0 SEH is now default on WIN32, you can try and turn that off. And the third thing that may influence the interfacing is that the default alignment on Windows has changed(was max 8, now 16). ---------------------------------------------------------------------- avra · 2020-08-28 13:07 Thank you all for your valuable input. It helped me to dig deeper. I have finally found the problem and fixed it. This worked under 2.6.4 but not on newer FPC: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  strServer: PChar;  strDummy: PChar = '                                                                                                  ' + #0;  lngNode, lngPort, lngBsize, lngError: longint;begin  lngDummy := 80;  strServer := strDummy;  lngError := pilg_getconnectedserver(strServer, lngDummy, lngNode, lngPort, GETFIRST); end; It worked on 3.2.1 after this fix: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  strServer: PChar;  strDummy: array[0..255] of char;  lngNode, lngPort, lngBsize, lngError: longint;begin  lngDummy := 80;  strServer := PChar(strDummy);  lngError := pilg_getconnectedserver(strServer, lngDummy, lngNode, lngPort, GETFIRST); end; ---------------------------------------------------------------------- PascalDragon · 2020-08-28 13:16 Quote from: avra on August 28, 2020, 03:07:17 pmThank you all for your valuable input. It helped me to dig deeper. I have finally found the problem and fixed it. This worked under 2.6.4 but not on newer FPC: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  strServer: PChar;  strDummy: PChar = '                                                                                                  ' + #0;  lngNode, lngPort, lngBsize, lngError: longint;begin  lngDummy := 80;  strServer := strDummy;  lngError := pilg_getconnectedserver(strServer, lngDummy, lngNode, lngPort, GETFIRST); end; String constants are ReadOnly starting with 3.0.0. And according to the documentation the pilg_getconnectedserver functions expects allocated memory so that it can write the server name there. But if the memory that the PChar points to is readonly then this results in an access violation. Quote from: avra on August 28, 2020, 03:07:17 pmIt worked on 3.2.1 after this fix: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var  strServer: PChar;  strDummy: array[0..255] of char;  lngNode, lngPort, lngBsize, lngError: longint;begin  lngDummy := 80;  strServer := PChar(strDummy);  lngError := pilg_getconnectedserver(strServer, lngDummy, lngNode, lngPort, GETFIRST); end; You can also directly pass PChar(strDummy) instead of using strServer. Please note that lngDummy contains the available space of the string buffer, so if the server name should be larger than 80 you'll only get 80 characters despite the string having enough space left. ---------------------------------------------------------------------- avra · 2020-08-28 13:38 Quote from: PascalDragon on August 28, 2020, 03:16:57 pmString constants are ReadOnly starting with 3.0.0. And according to the documentation the pilg_getconnectedserver functions expects allocated memory so that it can write the server name there. But if the memory that the PChar points to is readonly then this results in an access violation.Thank you. This explains nicely why code behaved as it did. Quote from: PascalDragon on August 28, 2020, 03:16:57 pmYou can also directly pass PChar(strDummy) instead of using strServer. Bits of code were taken from various places and strServer was used later in code, so at the end forum sample was not optimal. Thanks for pointing this out. Quote from: PascalDragon on August 28, 2020, 03:16:57 pmPlease note that lngDummy contains the available space of the string buffer, so if the server name should be larger than 80 you'll only get 80 characters despite the string having enough space left.Server name is netbios name and it has max length of 15. I was playing safe with 80.