Envision, Create, Share

Welcome to HBGames, a leading amateur game development forum and Discord server. All are welcome, and amongst our ranks you will find experts in their field from all aspects of video game design and development.

[Resolved] Accessing an external dll file

som4

Member

Hi i've been trying to make RPG Maker XP access an external dll's method using the following:

Code:
@read = Win32API.new 'MathFuncsDll', 'Add',['i','i'], 'i'

The dll file is in the same folder as Game.exe
Is was a tutorial i found written in VC++

Code:
// MathFuncsDll.cpp
// compile with: /EHsc /LD

#include "MathFuncsDll.h"

#include <stdexcept>

using namespace std;

namespace MathFuncs
{
    int MyMathFuncs::Add(int a, int b)
    {
        return a + b;
    }

    int MyMathFuncs::Subtract(int a, int b)
    {
        return a - b;
    }

    int MyMathFuncs::Multiply(int a, int b)
    {
        return a * b;
    }

    int MyMathFuncs::Divide(int a, int b)
    {
        if (b == 0)
        {
            throw new invalid_argument("b cannot be zero!");
        }

        return a / b;
    }
}

and

Code:
// MathFuncsDll.h

namespace MathFuncs
{
    class MyMathFuncs
    {
    public:
        // Returns a + b
        static __declspec(dllexport) int Add(int a, int b);

        // Returns a - b
        static __declspec(dllexport) int Subtract(int a, int b);

        // Returns a * b
        static __declspec(dllexport) int Multiply(int a, int b);

        // Returns a / b
        // Throws DivideByZeroException if b is 0
        static __declspec(dllexport) int Divide(int a, int b);
    };
}

I get the error:

Runtime error
GetProcAddress: Add or AddA

This has been driving me nuts for days now.  Any help would be great.
 
That error (<function_name> or <function_name>A) you got comes from the fact you´re using either an incorrect or inexisting name for a function inside the DLL. I know it because i´ve ventured in the Win32API world too, and got lots of similar errors :)

Guess it´s all because you´ve put your method inside a namespace. The final name generated by the compiler becomes all jaggy and strange, and unless you use a def file with a reasonable name, you´ll have to guess (or at least look at the name generated for your method from the .def file that the compiler should generate) the correct name for the method.

All because of name mangling. Many compilers generate different names from each other based on the same source and the call convention used. This becomes worse if you use methods from inside classes, structs or namespaces, because the compiler must transform the method's name and its scope into a reasonable name in C-style calls (blame "C with classes" lol).

Hmm i´d recommend you to either convert it to C code, use a .def file to rename your function calls when compiling your DLL, put your method outside the namespace (read it "put it in global scope"), use a less-decorated call convention(like __cdecl, so your final name would be more like the name of your method) or (maybe) use a wrapper around your DLL, like swig (although i have no idea on how you should use it, it would work. It has worked for other ppl :D)

BTW, if you can, check the .def file your compiler generated together with your DLL (if you enabled it, if not compile again and make sure you set the correct flags for it) to see the exported functions of your DLL so you´ll see what i´m talking about :)

(and sorry if i can´t help much, i´m not used to VC++...)
 
som4":jq4mqy4h said:
Thats a great help thanks.  Should be heading in the right direction now.
No problem! If ya need any help just ask!

Oh, and plz tell me if ya adress the problem somehow (no need to explain how exactly you did, i just need to be sure you solved your problem).
 

som4

Member

I managed to call a method from my dll eventually.  It didnt do anything but its a start. 

I have a new problem now though.  I'm not that much of a c++ programmer and wondered if you'd know how to pass a string using the Win32API?  I've used L in the return parameter but became stumped when i discovered the way C handles strings.  I eventually managed to get a method to return a string when it was created as a char* value equal to "hello".  Only problem was it returned it as 108811776. I'm clearly going wrong somewhere.  I've had a bash at some c tutorials but am still not really sure about how to use strings or char arrays.  Wondered if you or anyone knows how to do this?

Thanks

***Update***
I figured out how to retrieve a string using pointers instead, but still working on sending strings to the method.
I can send a string as a pointer to the method but i run in to a problem when it tries to use the string.

Code:
char* GetValue(char* newtring) {
	GetModuleFileName(NULL, (LPTSTR)module, MAXMODULE);
	
	char* str1 = newstring;
	
	return str1;
   
}

this produces the following "error C2065: 'newstring' : undeclared identifier"
The error is on the 4th line
 
You simply mispelled the variable name. Instead of putting newstring you put newtring in the arguments list :/

And of course, you should always use pointers to manage C strings. In Ruby you can fill a common string with null characters to reserve (allocate?) memory for the string, and to pass a strig to a C method just put a null character in the end of it.
 

som4

Member

Yeh i noticed the spelling mistake eventually, although i spent a good few hours messing with it til i noticed.  Cant believe it took me so long.  I figured out strings too eventually, now my next task is to actually do something useful with the dll.
 
Maybe you should pack the DLL with useful utilities like what the netplay project did, by calling the Win32 API (i mean the Windows's C Library). Well the possibilities are limitless, you just need to use your imagination lol :)

And good to see it´s solved. Good luck with your scripting ^^
 
This is a little off topic but it's still with DLLs..
I just ran a test with this code in RMVX
Code:
while i<100000000
  i+=1
end
and this in the DLL(C++)
Code:
while (i<100000000){i+=1;}
and this is the result:
DLL: 0.578  RMVX: 126.953 (those numbers are in seconds)

Witch means that DLLs are ALOT faster than Ruby/RGSS2
 

som4

Member

Yeh thats what my plan had been all along.  To design my own personal version of netplay.  I've got the dll doing simple things (took me a while to realise what the *char variable was all about, I'm obviously too used to Java's 'Strings').  Well I've been doing some googling and have loads of win32 API stuff which should keep me entertained for a long time.  Thanks again.

Thats quite interesting about the speed. I might try that in RMXP.
 
That´s kinda obvious, because Ruby implements its interpreter with C function calls, and because of that, if you implement the exact same task in both, of course the C version will be way faster (even more on your case, where you don´t call any functions, in ruby the interpreter may´ve called a few). This is valid for any interpreted language implemented in a lower level language (Python, Lua and all the like).
 

Thank you for viewing

HBGames is a leading amateur video game development forum and Discord server open to all ability levels. Feel free to have a nosey around!

Discord

Join our growing and active Discord server to discuss all aspects of game making in a relaxed environment. Join Us

Content

  • Our Games
  • Games in Development
  • Emoji by Twemoji.
    Top