Sign in to follow this  
Followers 0
JohnOne

Building a dll [Solved]

36 posts in this topic

#1 ·  Posted (edited)

I know this is a developers forum, but i think this belongs here.

I've tried making a simple math dll in visual studio 2010 following the walkthrough here

It built successfully, but the call from autoit returns @error = 3 "function" not found in the DLL file

mathdll.h

namespace MathFuncs
{
    class MyMathFuncs
    {
    public:
        // Returns a + b
        static __declspec(dllexport) double Add(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />;

        // Returns a - b
        static __declspec(dllexport) double Subtract(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />;

        // Returns a * b
        static __declspec(dllexport) double Multiply(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />;

        // Returns a / b
        // Throws DivideByZeroException if b is 0
        static __declspec(dllexport) double Divide(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />;
    };
}

mathdll.cpp

#include "MathDll.h"

#include <stdexcept>

using namespace std;

namespace MathFuncs
{
    double MyMathFuncs::Add(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
    {
        return a + b;
    }

    double MyMathFuncs::Subtract(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
    {
        return a - b;
    }

    double MyMathFuncs::Multiply(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
    {
        return a * b;
    }

    double MyMathFuncs::Divide(double a, double <img src='http://www.autoitscript.com/forum/public/style_emoticons/<#EMO_DIR#>/cool.png' class='bbc_emoticon' alt='B)' />
    {
        if (b == 0)
        {
            throw new invalid_argument("b cannot be zero!");
        }

        return a / b;
    }
}

#include <Array.au3>
$dll = DllOpen("mathdll.dll")
ConsoleWrite(@error & @LF)
If $dll = -1 Then
    MsgBox(0, "", "")
    Exit
EndIf
$call = DllCall($dll, "double", "Multiply", "double", 2, "double", 4); tried Add, Subtract, Divide. And "double:cdecl" as return type.
ConsoleWrite(@error & @LF)
DllClose($dll)
ConsoleWrite(@error & @LF)
_ArrayDisplay($call)

My question is, are there any settings I need to employ in the C++ project properties that are needed for a dll to work with autoit, or am I making a schoolboy error?

The console output is...

0

3

0

Appreciate anyones time. Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites



Does this help?

http://www.autoitscript.com/forum/index.php?showtopic=113441

I don't know about vc++, but I know that c# dlls are a different format to normal ones, and so can't be used from AutoIt. I'd try it with plain c++ (e.g. make a win32 program in the wizard)

Share this post


Link to post
Share on other sites

Yes Mat, it led me to a solution similar to the one in that thread.

Thanks for pointing it out.

No probs ;)

Whats it for exactly?

Share this post


Link to post
Share on other sites

Nothing swanky mate, just filling my lazy sunday afternoon, with something educational rather than surfung the usual crap on the internet.

I know learning how to make a dll will come in handy for me in the future.


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

I can see the title says solved but I feel I need to add something. If you have functions defined on classes, they can't be called without a reference to the class. It's much better for dll libraries to have file level functions.

Share this post


Link to post
Share on other sites

I dont know what file level functions are, but I mostly followed this tut in the end.

File level is not in a namespace or class. For example, all AutoIt functions are at file level, whereas c#'s methods are all in classes which are in namespaces.

Share this post


Link to post
Share on other sites

I see, then I think what I have are file level.

It is this format

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

With some prototypes and then the functions themselves.


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

DllMain is at file level, yes.

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I have a little question, about DllMain if anyone can answer it for me.

Regarding the code above, in DllMain the switch "switch (ul_reason_for_call)".

Does an Autoit3 DllOpen/DllCall involve any of the given cases ?

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

Yes, I presume AutoIt uses the LoadLibrary function so that when you open a dll, it calls with DLL_PROCESS_ATTACH, and with DllClose it will use DLL_PROCESS_DETACH

You can test that easily enough.

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

According to (http://en.wikibooks.org/wiki/Windows_Programming/Dynamic_Link_Libraries)

DLL_PROCESS_ATTACH -- a new program has just linked to the library for the first time.

DLL_PROCESS_DETACH -- a program has unlinked the library.

DLL_THREAD_ATTACH -- a thread from a program has linked to the library.

DLL_THREAD_DETACH -- a thread from a program has just unlinked the library.

" ...if you aren't interested in any of the reasons, you can remove the entire switch statement from your program and return TRUE."

Edited by jaberwocky6669

Share this post


Link to post
Share on other sites

Thanks gentlemen.

That being true, what I am intersted in is a way to employ "LPVOID lpReserved" from a DllOpen in Autoit, like passing it an argument??

I have a feeling I'm not going to get the answer I want, but I looked much sillier before this so I wont be braeking my record.


AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

You cannot pass an extra parameter to DLLMain.

Waht is the param you want to pass?


*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

I'm after a function in the dll to be executed, but only once upon it being opened, and using a parameter passed.

The paramater type is not important to me, It can be any type available in Autoit.

EDIT: except bool.

For instance concider this psuedo

I use DllCall($dll, "int", "func")

$Dll is opened, and another internal function is performed, then "func" and the dll is closed.

I use DllOpen($dll,"int",12345)

DllCall($dll, "int", "func2")

DllCall($dll, "int", "func3")

DllClose($dll)

$Dll is opened, and another internal function is performed, then "func"

then "func2" them "func3"

and the dll is closed.

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

Wouldn't this work?

BOOL APIENTRY DllMain(MODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        // function();
        break;

        case DLL_THREAD_ATTACH:
        break;

        case DLL_THREAD_DETACH:
        break;

        case DLL_PROCESS_DETACH:
        break;
    }
    
    return TRUE;
}
Edited by jaberwocky6669

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

It's not difficult to add a function prototype.

Edited by Richard Robertson

Share this post


Link to post
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
Sign in to follow this  
Followers 0