Calling a C style DLL succeeds and then AutoIt crashes - c

I'm trying to call a C style library called "universal speech" from AutoIt 3 (latest version). I get the desired action from the function I'm calling but after I get the response AutoIt crashes saying "AutoIt has stopped working, Windows can search for the solution..." Am I doing something wrong?
AutoIt:
#notrayicon
dllcall("UniversalSpeech.dll", "int", "speechSayA", "str", "test 123", "int", 1)
sleep(1000)
universal speech.h:
#ifndef ____UNIVERSAL_SPEECH_H__
#define ____UNIVERSAL_SPEECH_H__
#if defined __WIN32 || defined __WIN64
#define export __declspec(dllexport)
#else
#error Platform currently unsupported
#endif
#ifdef __cplusplus
extern "C" {
#endif
int export speechSayA (const char* str, int interrupt) ;
#ifdef __cplusplus
} // extern "C"
#endif
#endif
I successfully did this in other programming languages but AutoIt doesn't seem to like it.

"binhnx" on AutoIt forum solved my problem:
This library uses the cdecl calling convention and AutoIt by default uses the stdcall calling convention. Cdecl is supported, though you have to tell AutoIt that you want to use it by entering :cdecl next to the return type of the function you're calling.
So in my case instead of:
dllcall("UniversalSpeech.dll", "int"...)
you'd go like this:
dllcall("UniversalSpeech.dll", "int:cdecl"...)
Which solves the crash.

Related

LabVIEW + C-DLL: Access violation (0xC0000005) at EIP = 0x00000000

Information:
LabVIEW: 2019
Version: 19.0.1 (32-bit)
Operating system: Windows 64-bit
Labview crashes completely after an indefinite time. I call three functions of the C-DLL. I loop through all the functions of the DLL over and over again. After about 2 minutes to an hour Labview crashes without reason.
Calling of OpenConnection():
Calling of QueryOpenConnectionStatus():
Calling of CloseConnection():
Type definition of TConnectionResult
Follow the given Headerfile.h
#ifndef __epMCOMLib_h_
#define __epMCOMLib_h_
#include <stdint.h>
#include <stddef.h>
#define DLLIMPORT __declspec(dllimport)
#pragma pack (push,1)
typedef struct {
uint16_t DLLFailureCode;
uint8_t ConnectionStatus;
uint32_t SystemFailureCode;
} TConnectionResult;
#pragma pack (pop)
#ifdef __cplusplus
extern "C" {
#endif
DLLIMPORT uint16_t __cdecl OpenConnection(uint8_t PortType,
char * PortName,
uint32_t OnConnectSucces,
uint32_t * Handle);
DLLIMPORT void __cdecl QueryOpenConnectionStatus(uint32_t Handle,
TConnectionResult * Result);
DLLIMPORT uint16_t __cdecl CloseConnection(uint32_t Handle);
#ifdef __cplusplus
} // extern "C"
#endif
#endif //#ifndef __epMCOMLib_h_
The DLL works perfectly. For this I integrated the DLL in Python ,LabWindows/CVI, C++ and Delphi. There is no crash in these programming languages!
Can anyone give me any useful tips on how to further isolate or eliminate the error.
Even if a function of the DLL has been executed and the DLL is then closed, it still causes a crash. As if it's still in memory. It feels like looking for a needle in a haystack.
Run the thread on the UI thread instead of any thread!
In the log file of the DLL I could see that the thread is attached and detached. I suspect this is causing a memory violation. Since Labview is shot down by its called DLL.
In my experience, sometimes DLL called with LabVIEW causes this kind of problems and with no specific reasons and solutions (even for the NI technical support).
Try to launch your LabVIEW applicatin with Administrator privilegies. In some cases, this solves the problem.

Stripping specific functions on compile time

I'm writing a C program that uses a custom logging function to debug my program. Whenever I compile my program as a release version, I want all of my logging functions to be stripped from the code so it won't show up if someone tries to disassemble it.
Take the following example:
#include <stdio.h>
void custom_logging_function(char* message)
{
// Do something here
}
int main()
{
custom_logging_function("Hello world"); // This call should be removed.
return 0;
}
How could I make it so that the custom_logging_function and it's arguments aren't compiled into my program without having to write include guards everywhere throughout my code? Thank you
You can use pre-processor flags, for example:
#include <stdio.h>
#ifdef DEBUG
void custom_logging_function(char* message)
{
// Do something here
}
#else
#define custom_logging_function(x) ((void) 0)
#endif
int main()
{
custom_logging_function("Hello world"); // This call should be removed.
return 0;
}
With this code you will have to tell the "debug" target to define DEBUG, if you want to define something specifically for the "release" target you can replace #ifdef DEBUG with #ifndef NDEBUG and add the NDEBUG flag to the "release" definitions.
Edit:
Changed #define custom_logging_function(x) 0 to #define custom_logging_function(x) ((void) 0) inspired by #JoachimPileborg his answer.
Assuming you only want the logging calls to happen in a debug-build of your application, and not the release build you send to customers, you can still use the preprocessor and conditional compilation for it. It can be made vert simple though by using macros instead of having checks at every call.
Something like this in a heder file:
#ifdef _DEBUG
void custom_logging_function(char* message);
#else
# define custom_logging_function(message) ((void) 0)
#endif
You could use an empty macro body for the release-macro, but that can cause some compilers to give "empty statement" warnings. Instead I use an expression casted to void (to tell the compiler that the result of the expression will not be used). Any smart compiler will not include the expression after optimization.

weird c function syntax

I know my C up to this point. I was looking at the source files of PHP I downloaded, and I saw this strange syntax:
PHPAPI int php_printf(const char *format, ...)
{
// code...
}
What does the PHPAPI do before the return type int? I've tried searching all over and I can't understand what this means. Is it a second return type? It can't be because the function does return an int. Maybe it extends to some other struct declared in a header file?
The hard way:
Go to the makefile and add in the line that compiles the sources: -E, by doing so you will see the source cose after the preprocessing phase.
The easy way:
Search all the project for PHPAPI:
find it in php.h:
#ifdef PHP_WIN32
#include "win95nt.h"
# ifdef PHP_EXPORTS
# define PHPAPI __declspec(dllexport)
# else
# define PHPAPI __declspec(dllimport)
# endif
#define PHP_DIR_SEPARATOR '\\'
#else
#define PHPAPI
#define THREAD_LS
#define PHP_DIR_SEPARATOR '/'
#endif
Now what you need to know is what is __declspec(dllexport) and what is __declspec(dllimport)
In the SO thread- What is __declspec and when do I need to use it?
see Alexander Gessler answer:
The canonical examples are __declspec(dllimport) and
__declspec(dllexport), which instruct the linker to import and
export (respectively) a symbol from or to a DLL.
// header
__declspec(dllimport) void foo();
// code - this calls foo() somewhere in a DLL
foo();
(__declspec(..) just wraps up Microsoft's specific stuff - to
achieve compatibility, one would usually wrap it away with macros)

#Define Entire function call with arguments?

I have a program that I am running on two different compilers, and each compiler has a different file handling library. For example on library requires:
fwrite(buffer,size,elements,file)
While the other is:
f_write(file,buffer,size,elements)
is there anyway I could use a global #define in my main header file inside of a #ifdef statement that would allow me to seamlessly transition between compilers?
Sure:
#ifdef STUPID_COMPILER
# define fwrite(ptr, size, nitems, stream) f_write(stream, ptr, size, nitems)
#endif
Then just use fwrite() in your code -- no wrapper function needed. The preprocessor will translate it to an f_write() call if you're using the compiler/library that requires that.
You could make a new function:
size_t my_fwrite(...)
{
#ifdef REAL_FWRITE
return fwrite(buffer,size,elements,file);
#elif F_WRITE
return f_write(file,buffer,size,elements);
#else
#error "No fwrite"
#endif
}
What kind of implementation doesn't provide fwrite but has f_write ?

Error C2491 on C source with Visual studio 8

i'm really noob in C. I just need to compile a ANSI C source to get a dll.
During compilation i get this error:
C2491: 'SelectML': definition of dllimport function not allowed
Where SelectML is a public function with this definition:
int CALLINGCONV SelectML(WORD fid, int nSlot)
{
WORD SW;
int x;
BYTE pSend[2];
pSend[0]=(BYTE)((fid&0xff00)>>8);
pSend[1]=(BYTE)(fid&0x00ff);
x=SendAPDUML(hCards[nSlot],APDU_SELECT,2,0,pSend,0,&SW);
if (x!=C_OK) return x;
if (SW!=0x9000) return SW;
return C_OK;
}
I'm sure the C source is good, maybe it is just a Visual Studio configuration...
This is another linked header:
#ifndef LIBSIAECARDT_H
#define LIBSIAECARDT_H
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(USE_STDCALL)
#define USE_STDCALL 1
#endif
#ifdef _WIN32
# if USE_STDCALL == 1
# define CALLINGCONV_1 _stdcall
# else
# define CALLINGCONV_1
# endif
# if defined(LIBSIAE_EXPORTS)
# define LIBSIAEAPI __declspec(dllexport)
# else
# define LIBSIAEAPI __declspec(dllimport)
# endif
# define CALLINGCONV LIBSIAEAPI CALLINGCONV_1
#else // ! _WIN32
# define CALLINGCONV
# define LIBSIAEAPI
# define CALLINGCONV_1
typedef unsigned int UINT;
#endif // _WIN32
It's common to have a macro like CALLINGCONV conditionally defined as __declspec(dllimport) or __declspec(dllexport) so that the same header file can be used in the library source and in the code using the library. Your build should probably define something that makes it use dllexport. Check how CALLINGCONV is defined or (preferably) consult any build documentation that came with the code.
Quoted in MSDN says it all. Do not define the function. Declaration is good. What you are doing here is defining SelectML which for sure is generating your C2491 Error.
Here's an alternative. Stop using MSVC. They explicitly dropped support for anything after C90. Use an actual C compiler for C code.

Resources