Welcome Guest [Log In] [Register]
We hope you enjoy your visit.


You're currently viewing the Ultimate 3D Community as a guest. This means that you can only read posts, but can not create posts or topics by yourself. To be able to post you need to register. Then you can participate in the community active and use many member-only features such as customizing your profile, sending personal messages, and voting in polls. Registration is simple, fast, and completely free.

Join our community!

If you are already a member please log in to your account to access all of our features:

Username:   Password:
Add Reply
Creating A DLL for GameMaker; Using Microsoft Visual C++ 2008
Topic Started: Oct 22 2009, 02:23 AM (3,874 Views)
NGen
Member Avatar
Advanced Member
[ *  *  * ]
As many of you already know, DLL's can be used to greatly extend the capabilities of GameMaker, sometimes to a point (As the U3D DLL has shown) where the DLL can do something that GameMaker could probably never do (or wouldn't be able to do for quite a while). Unfortunately, a simple explanation of how to create a DLL has been missing for quite some time, so I'd like to bring this subject to light.

(Dr. Best, please read this tutorial thoroughly. You are definitely more advanced on this subject than I am, and I don't want to be giving any poor suggestions. This is just what I've learned.)

Spoiler: click to toggle


To start off, we need to set up a DLL project. Open up VC++, and create a new project (ctrl+shift+N). Select Win32 Project, name it, and click OK. When the Application Wizard comes up, press next, and select DLL under the "Application type" section. Do not select any other options, and click Finish.


You will most likely be given the following files:

-stdafx.h
-targetver.h
-dllmain.cpp
-stdafx.cpp
-<Project Name>.cpp

Delete EVERYTHING except "dllmain.cpp", and turn off the Precompiled Headers option ( Project-> Properties-> Configuration Properties-> C/C++-> Precompiled Headers-> Create/Use Precompiled Header ). Then put the following at the top of the dllmain.cpp file:
Code:
 
#include <windows.h>

If stdafx.h is included as well, delete that.


Now, in the dllmain.cpp file, you'll see the definition of a function called "DllMain". This function is called whenever the DLL is loaded into a process, and can be treated as the main function in a terminal application, or the WinMain function in a Win32 application. In the 39DLL, this was used to create the default data buffer for sending messages. I think that a socket was also created. This was also used to delete those objects.

In this function you should see a switch statement using the variable "ul_reason_for_call". This specifies why the function was called (obviously). UL_PROCESS_ATTATCH and UL_PROCESS_DETATCH are used for whenever the DLL is loaded into a process and when it is unloaded from a process. I believe the other 2 are for loading into... well, threads.


Note: This function is completely optional. No errors will occur if you remove this function.

So, let's start adding some functions. We first have to make sure that we know how to say that a function is being exported into the DLL. We'll start by using this:

Code:
 
#define DLLEXPORT extern "C" __declspec ( dllexport )


Let's pick this apart:

  • #define - A basic pre-processor directive, this basically just says that when the code is compiled, go through it first and replace every spot where "DLLEXPORT" is found with "extern "C" ...".

  • extern "C" - In C++, we have the option of using classes, namespaces, and overloaded functions to allow us to create multiple things with the same name. However, this doesn't just happen by magic. If 2 things have the same name, something needs to be added to the name so that we can differentiate it from other things with the same name. This process is called Name Mangling, where the parameters used to create a variable, method, struct, etc. are blended into the name to make it unique. If we didn't have this extern "C" here, the name of the function exported would be much different than the name we gave the function, and so we would get an error when trying to load the function because the names wouldn't match. extern "C" disables name mangling.

  • __declspec ( dllexport ) - This is the part that actually says "Hey, VC++, we're going to be putting this function into the DLL!"



So, now we know how to say that we're going to export a function, let's put this to use:

Code:
 
double DLLEXPORT Multiply ( double Num1, double Num2 ) {
return Num1*Num2;
}


Note that this function is not that different from our usual function, just that we're using DLLEXPORT within our definition. But if you are putting your exports into a header file (basically if you are declaring your function first), you only need to use DLLEXPORT on the declaration of the function, not the definition.

Then, compile the program (If you use the Start Debugging function, make sure the drop-down menu is set to Release), get the DLL, make a GMK file and test it! I defined the function in GML using:

Code:
 
global.Mult = external_define ( "My DLL.dll", "Multiply", dll_cdecl, ty_real, 2, ty_real, ty_real );

Please notice that I use dll_cdecl for the 3rd argument. Remember the 'extern "C"'?

So, if you set up the DLL as I've explained it and you have set it up right, then you should be able to use the function to successfully multiply 2 numbers together! Yay! Math! :cow:




Now, I know this tutorial is unfinished, but I'm running out of time so I'll just have to update this later on.
Edited by NGen, Oct 24 2009, 08:23 PM.
Offline Profile Quote Post Goto Top
 
NGen
Member Avatar
Advanced Member
[ *  *  * ]
WHAT

THE

HELL.


It chopped off half of the tutorial! T_T


EDIT: Nevermind, I did a list BB wrong. :doh:
Edited by NGen, Oct 22 2009, 02:27 AM.
Offline Profile Quote Post Goto Top
 
Dr. Best
Member Avatar
Administrator
[ *  *  *  *  *  * ]
Nice tutorial. I read something similar on the GMC years ago, when I started making Ultimate 3D. There is nothing wrong with it. One thing I'd like to add is that you should be using scripts like U3D's ExternalDefineDouble(...) and ExternalDefineWithString(...), whenever you import functions into Game Maker. Otherwise it is very easy to do something wrong and then your functions won't be called.

Also here is some info about what extern "C" really means: In C++ you have name mangling. This means that your compiled code does not contain the original function names, but a combination of the function name and its associated types. This way the names are still unique when functions are overloaded. You get to see these mangled names in linker errors. They have lots of @ signs. extern "C" does nothing other than disabling name mangling.
Offline Profile Quote Post Goto Top
 
NGen
Member Avatar
Advanced Member
[ *  *  * ]
Oh yeah, I forgot about name mangling. Thanks for the clarification, I'll put in the correct information when I finish the tutorial completely.
Offline Profile Quote Post Goto Top
 
skarik
Member Avatar
kitten eating scum
[ *  *  *  *  *  * ]
This is a good tut. What ever happened to the one on the GMC? Besides the fact it redefined a keyword, it was okay.

I like yours better, though. More in depth to what's going on.


Something that's kinda weird: some DLL's thrown into GM will just fail in WINE if there's no DLLMain function for the DLL. I've been able to get a very consistent result with this. Do you guys know why they fail?
Edited by skarik, Oct 23 2009, 12:37 AM.
Blog|EHS
Offline Profile Quote Post Goto Top
 
NGen
Member Avatar
Advanced Member
[ *  *  * ]
Remember that WINE is an emulator. It can't do everything exactly as Windows does it.
Offline Profile Quote Post Goto Top
 
Gandalf20000
Member Avatar
Geek
[ *  *  *  *  *  * ]
NGen
Oct 23 2009, 02:02 AM
Remember that WINE is an emulator.
Don't let the development team or Linux buffs hear you say that.
Offline Profile Quote Post Goto Top
 
zelda4evr
Member Avatar
Forum God
[ *  *  *  *  *  * ]
i don't understand why they get so offended, all it does is emulate what windows does, and the word emulate means, to try to behave like(or something close to that)

Posted Image
Offline Profile Quote Post Goto Top
 
skarik
Member Avatar
kitten eating scum
[ *  *  *  *  *  * ]
zelda4evr
Oct 24 2009, 05:54 PM
i don't understand why they get so offended, all it does is emulate what windows does, and the word emulate means, to try to behave like(or something close to that)
'Cause it does do what Windows does. You install Wine, to a noob like me, and it looks like I'm just installing the Windows system directory.
Blog|EHS
Offline Profile Quote Post Goto Top
 
Gandalf20000
Member Avatar
Geek
[ *  *  *  *  *  * ]
Wine Is Not an Emulator. That's why they get upset. I don't understand it either. They claim it's not an emulator because it doesn't emulate everything, it just provides a compatibility layer of alternate DLLs and substitution processes. And it's not an emulator how? It copies the functions and behaviors of Windows, and yet it isn't an emulator? Doesn't make sense to me either.
Offline Profile Quote Post Goto Top
 
skarik
Member Avatar
kitten eating scum
[ *  *  *  *  *  * ]
Not in the emulator as in the sense that most of us take it as, I'm guessing. I assume an emulator is always going to be slower. Might be because I have less crap running, but my games run faster on Wine with debug mode turned off than they ever did in Windows.

Still, I get a buttload of problems dealing with the registry.
Edited by skarik, Oct 24 2009, 07:05 PM.
Blog|EHS
Offline Profile Quote Post Goto Top
 
NGen
Member Avatar
Advanced Member
[ *  *  * ]
I'm guessing it's because they aren't having the entire Windows GUI added into it.
Offline Profile Quote Post Goto Top
 
skarik
Member Avatar
kitten eating scum
[ *  *  *  *  *  * ]
NGen
Oct 24 2009, 07:38 PM
I'm guessing it's because they aren't having the entire Windows GUI added into it.
Yeah, probably.
Blog|EHS
Offline Profile Quote Post Goto Top
 
NGen
Member Avatar
Advanced Member
[ *  *  * ]
NOTE: Updated tutorial on the definition of extern "C". I know I was going to add more to this, but I can't remember what it was. If anyone has any suggestions, feel free to give them.

Alright, quick question for Dr. Best:

If the only thing extern "C" does is disable name mangling for a function/whatever, then, in theory, couldn't we still use templates and other C++-style constructs?
Edited by NGen, Oct 24 2009, 08:26 PM.
Offline Profile Quote Post Goto Top
 
Dr. Best
Member Avatar
Administrator
[ *  *  *  *  *  * ]
NGen
Oct 24 2009, 08:25 PM
Alright, quick question for Dr. Best:

If the only thing extern "C" does is disable name mangling for a function/whatever, then, in theory, couldn't we still use templates and other C++-style constructs?
Basically a DLL is similar to a library, which is like a replacement for C++ source files. Templates have to be in headers, so those can never be in DLLs. Calls to member functions of classes use a different calling convention (this-call), so those can not be used by Game Maker either. This also kills the possibility of using things like inheritance through Game Maker. Basically the only thing you can get into Game Maker are functions, which are made to be used through Game Maker. Global functions with double and const char* parameters/return types and some special markers.
Offline Profile Quote Post Goto Top
 
Go to Next Page
« Previous Topic · Tutorials · Next Topic »
Add Reply