oli_the_true_one Posted June 15, 2021 Share Posted June 15, 2021 Hello everyone, I'm writing a small program that uses an external dll called "EAPI.dll". The SDK provides a 32 bits version and a 64 bits version of that DLL. The 64 bits version works fine. However, the 32 bits version results in an application crash. The 32 bits version: expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=n #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <MsgBoxConstants.au3> #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> Global $aResult Global $hEAPIdll Global $IsRunning=True Global $sIPSrawDataReturned Global $iIPStypeReturned HotKeySet("{ESC}","_Terminate") ;Press ESC key to terminate ;the EAPI.dll functions provided by Advantech $hEAPIdll = DllOpen("D:\EAPI\X86\EAPI.dll") If ($hEAPIdll = -1) Then MsgBox($MB_ICONERROR+$MB_OK,"IPS-AE Fatal Error","Error while opening EAPI.dll.") Exit EndIf ;Create the callback function for EApiUPSInitDev. Local $hAtCallback = DllCallbackRegister("_getIPSAEdata", "none", "int;str") $aResult = DllCall($hEAPIdll, "DWORD", "EApiUPSInitDev", _ "str", "COM1", _ "ptr", DllCallbackGetPtr($hAtCallback)) While $IsRunning Sleep(100) WEnd Func _Terminate() $IsRunning=False DllClose($hEAPIdll) DllCallbackFree($hAtCallback) EndFunc ; Callback Procedure Func _getIPSAEdata($type, $str) ConsoleWrite("$type: " & $type & @CRLF) ConsoleWrite("$str: " & $str & @CRLF) EndFunc ;==>_getIPSAEdata The 64 bits version: expandcollapse popup#Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_UseX64=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include <MsgBoxConstants.au3> #include <AutoItConstants.au3> #include <GUIConstantsEx.au3> Global $aResult Global $hEAPIdll Global $IsRunning=True Global $sIPSrawDataReturned Global $iIPStypeReturned HotKeySet("{ESC}","_Terminate") ;Press ESC key to terminate ;the EAPI.dll functions provided by Advantech $hEAPIdll = DllOpen("D:\EAPI\X64\EAPI.dll") If ($hEAPIdll = -1) Then MsgBox($MB_ICONERROR+$MB_OK,"IPS-AE Fatal Error","Error while opening EAPI.dll.") Exit EndIf ;Create the callback function for EApiUPSInitDev. Local $hAtCallback = DllCallbackRegister("_getIPSAEdata", "none", "int;str") $aResult = DllCall($hEAPIdll, "DWORD", "EApiUPSInitDev", _ "str", "COM1", _ "ptr", DllCallbackGetPtr($hAtCallback)) While $IsRunning Sleep(100) WEnd Func _Terminate() $IsRunning=False DllClose($hEAPIdll) DllCallbackFree($hAtCallback) EndFunc ; Callback Procedure Func _getIPSAEdata($type, $str) ConsoleWrite("$type: " & $type & @CRLF) ConsoleWrite("$str: " & $str & @CRLF) EndFunc ;==>_getIPSAEdata In the console, I can see that the callback function has been called by the DLL, but ~5 seconds later, AutoIT crashes. Here is the provided CPP example for the DLL functions I'm trying to use in AutoIT: // IPS-AE_Sample.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <Windows.h> #include "atIPSAE.h" #include "atEAPI.h" using namespace std; using namespace EApiCommonDLL; HINSTANCE hDLL = NULL; void atCallBack(CallBackType type, char* str) { printf("======================\ntype: %d\n%s\n==========================\n", type, str); }; void setTimetoDev(int t1, int t2) { if(hDLL) { EAPIFunction(hDLL, EApiUPSSetDCinLostDelayTime); if(EApiUPSSetDCinLostDelayTime){ char response[0xff] = {0}; unsigned int res = EApiUPSSetDCinLostDelayTime(t1, response, 0xff); if(res == 0)printf("setDCinLostDelayTime result => %s\n", response); } EAPIFunction(hDLL, EApiUPSSetDCoutCutOffDelayTime); if(EApiUPSSetDCoutCutOffDelayTime){ char response[0xff] = {0}; unsigned int res = EApiUPSSetDCoutCutOffDelayTime(t2, response, 0xff); printf("setDCoutCutOffDelayTime result => %s\n", response); } } } void runIPS_AE(char* comport) { hDLL = OpenEAPI(); if (hDLL == NULL) { printf("EAPI.dll Load Failed! 0x%X\n", GetLastError()); return; } EAPIFunction(hDLL, EApiUPSInitDev); //AdvIPSAEOBJ pobj = (AdvIPSAEOBJ)GetProcAddress(hDLL, "getAdvIPSAE"); if (EApiUPSInitDev != NULL) { if(!EApiUPSInitDev(comport, (IPSAEResopne)atCallBack)) { printf("start, there will send a callback automatically.....\n"); getchar(); setTimetoDev(300, 5); } } else { printf("GetProcAddress \"getAdvIPSAE\" Failed! 0x%X\n", GetLastError()); } } void byeIPS_AE() { if (hDLL) { //delAdvIPSAE delpobj = (delAdvIPSAE)GetProcAddress(hDLL, "AdvIPSAE::delAdvIPSAE"); //delAdvIPSAE delpobj = (delAdvIPSAE)GetProcAddress(hDLL, "delAdvIPSAE"); EAPIFunction(hDLL, EApiUPSDeinitDev); if (EApiUPSDeinitDev != NULL) { EApiUPSDeinitDev(); Sleep(1000); CloseEAPI(hDLL); } } } int main(int argc, char* argv[]) { if(argc < 2) { printf("example: IPS-AE_Sample.exe COM1\n"); return -1; } runIPS_AE(argv[1]); getchar(); byeIPS_AE(); return 0; } Does somebody have a clue on what's going on ? I would appreciate any suggestion. I've put the DLLs in the attached files and also some screenshots of the developper guide provided with the SDK. Thank you for your help +++ EAPI.rar Link to comment Share on other sites More sharing options...
Solution TheXman Posted June 15, 2021 Solution Share Posted June 15, 2021 (edited) Assuming that everything else is correct, the most common reason for an immediate crash, when executing in 32bit mode, is that your APIs use the cdecl calling convention. By default, AutoIt uses stdcall. So you need to add ":cdecl" to all of your return data types. example: $aResult = DllCall($hEAPIdll, "DWORD:cdecl", "EApiUPSInitDev", _ "str", "COM1", _ "ptr", DllCallbackGetPtr($hAtCallback)) Read more about it in the DllCall help file topic. You can leave the :cdecl when running in 64bit mode, it'll be ignored.  Edited June 15, 2021 by TheXman oli_the_true_one, FrancescoDiMuro and Danyfirex 2 1 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
oli_the_true_one Posted June 15, 2021 Author Share Posted June 15, 2021 Hello TheXman, Thank you so much for your advice, indeed the missing ":cdecl" in the return type was causing the crash in 32 bits. I can't believe I've been stuck for hours and hours because of this ^^ Problem solved ! 🙂 Link to comment Share on other sites More sharing options...
TheXman Posted June 15, 2021 Share Posted June 15, 2021 (edited) We've all been there. You're welcome. Edited June 15, 2021 by TheXman oli_the_true_one and FrancescoDiMuro 2 CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now