Jump to content

DLLCall - no return value?


Recommended Posts

Hi everyone,

I have written a simple DLL using the Mingw32 (http://mingw.org) compiler using the C programming language.

The DLL worked from C and C++ (naturally), but I have encountered some problems when trying to access it from AutoIt.

I use version 3.1.1 from April 7.

I have attached the code for the DLL, the simple script I use to call it and the DLL itself.

Here are some questions; I hope they would be answered:

1) What DLL calling convention is to be used from within the DLL? Is it to be __declspec or __stdcall?

2) AutoIt returns nothing when calling the MyMessageBox function (see the script), even though the function in the DLL is declared as to return an int. How do I obtain the value from the function MyMessageBox, if I can't get it like I've done in my script?

I think that was all for now.

Yours sincerely,

Peter.

http://www.tdlsoftware.org

cpp.zip

Link to comment
Share on other sites

1) What DLL calling convention is to be used from within the DLL? Is it to be __declspec or __stdcall?

<{POST_SNAPBACK}>

The calling convention should be WINAPI which is __stdcall.
Link to comment
Share on other sites

Thank you for the answers.

If I change the DLL calling convention, a new problem arises - nothing happens in the DLL.

Here's the simplest example of a DLL written in C and its associated script:

#include <windows.h>

extern "C" void WINAPI Hello() {

MessageBox(NULL, "Hello World", "Ok", 0);

}

BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ ,

DWORD reason /* Reason this function is being called. */ ,

LPVOID reserved /* Not used. */ )

{

switch (reason)

{

case DLL_PROCESS_ATTACH:

break;

case DLL_PROCESS_DETACH:

break;

case DLL_THREAD_ATTACH:

break;

case DLL_THREAD_DETACH:

break;

}

/* Returns TRUE on success, FALSE on failure */

return TRUE;

}

And the AutoIt script:

$dll = DllOpen("Peter.dll"); In this case, I saved the DLL as Peter.dll

$result = DllCall($dll, "none", "Hello")

DllClose($dll)

However, the message box does not show up... I have no clue as to what to do next...

What's wrong here?

Any help is very much appreciated.

Yours sincerely and thank you,

Peter.

Link to comment
Share on other sites

Well usually I use _declspec when I create a Dll. Because that's just how I learned, althought maybe it's incorrect -- it work's. I was also taught to write my functions in my Dll after all the process stuff. Like this:

/* Replace "dll.h" with the name of your header */
#include "dll.h"
#include <windows.h>

}
BOOL APIENTRY DllMain (HINSTANCE hInst   /* Library instance handle. */ ,
                       DWORD reason     /* Reason this function is being called. */ ,
                       LPVOID reserved   /* Not used. */ )
{
    switch (reason)
    {
      case DLL_PROCESS_ATTACH:
        break;

      case DLL_PROCESS_DETACH:
        break;

      case DLL_THREAD_ATTACH:
        break;

      case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}

extern "C"__declspec(dllexport) int MyMessageBox(char* String){
       MessageBox(NULL, String, "I am called correctly!", MB_OK);
       return 123;
}

I also changed your code for the function, because you're EXPORTING the dll function. And you didn't specify a return type. (This may be wrong changes, but this is what it looks like in C++) Also, as w0ter stated, I changed the $result var in the msgbox to $result[0]... DllCalls in autoit always return in arrays, I think. I've attached a zip with a Dll, source, and au3 script that all correctly work and compiled OK... Hope this helps :">

FootbaG
Link to comment
Share on other sites

Well usually I use _declspec when I create a Dll. Because that's just how I learned, althought maybe it's incorrect -- it work's. I was also taught to write my functions in my Dll after all the process stuff. Like this:

<snip>

I also changed your code for the function, because you're EXPORTING the dll function. And you didn't specify a return type. (This may be wrong changes, but this is what it looks like in C++) Also, as w0ter stated, I changed the $result var in the msgbox to $result[0]... DllCalls in autoit always return in arrays, I think. I've attached a zip with a Dll, source, and au3 script that all correctly work and compiled OK... Hope this helps :">

<{POST_SNAPBACK}>

The code was fine (at a quick glance, anyway); it did not need changed. Extern "C" changes the name linkage/name decoration to be C style which means it will be exported correctly without the __declspec(dllexport) line. The __stdcall calling convention is required or there will be memory leaks. And what does it matter if there is a return value or not? You think DllCall() is that sensitive that it MUST have a return value? Try again.

Black-Glawses, are you sure there isn't a typo in the DLL name? Can you try it without DllOpen/DllClose (Those aren't needed for such a simple example). There's nothing wrong with your code so I suspect its just a silly user mistake on your part. Have you looked at the DLL with an export viewer to make sure the function is exported correctly? Have you checked the @error macro after calling DllCall() to see if its set?

Link to comment
Share on other sites

Thank you very much for your answers, everyone.

They've helped me solve the problem at hand. I asked some C guys for help - and they told me I was to do the following:

__declspec(dllexport) int __stdcall FuncName() {}

and it works beautifully.

A few notes about this in the documentation would be very nice. (For instance, a very simple example in C of a DLL). Also, it would be nice if the documentation stated exactly what to call with words rather than examples - a combination of the two would be nice.

Again, thanks a thousand times for all the help,

Peter.

http://tdlsoftware.org

Link to comment
Share on other sites

Thank you very much for your answers, everyone.

They've helped me solve the problem at hand. I asked some C guys for help - and they told me I was to do the following:

__declspec(dllexport) int __stdcall FuncName() {}

and it works beautifully.

A few notes about this in the documentation would be very nice. (For instance, a very simple example in C of a DLL). Also, it would be nice if the documentation stated exactly what to call with words rather than examples - a combination of the two would be nice.

Again, thanks a thousand times for all the help,

Peter.

http://tdlsoftware.org

<{POST_SNAPBACK}>

Ahhh, now I recall, your post reminds me of the difference in how the conventions work:
  • __stdcall/__fastcall - As you show, __declspec(dllexport) must be used.
  • __cdecl - extern "C" __declspec(dllexport) must be used. The extern "C" changes the linkage/name decoration so that the function name won't get mangled.
I usually just use a module definition file anymore and had forgotten the correct syntax for exporting it from the code itself.
Link to comment
Share on other sites

Well, I do the same - I just let my C++ compiler do the necessary stuff and use it with simple import libraries. It gives me a lot greater flexibility, since my DLLs are to be in the directory for my programs to work.

Take care, and thank you once again for all the help you have offered me,

Peter.

http://www.tdlsoftware.org

P.S.: If any of you are in need of a simple DLL for Microsoft Speech API 5.1, I have one you may try - it encapsulates all the COM things so that you can concentrate on the things at hand. Please contact me from the website if you are interested.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...