I have Visual Studio installed with MSVC as the help file says we should be using. I can't wrap my head around how to make a .dll file for runtime stuff. ChatGPT seemed to think I needed to download agsplugin.h but I didn't need the other files in the engine/plugins folder, but you can't really trust what ChatGPT says.
I did a new project / DLL
I'm trying various things, but it's complaining about things. Is there something simple that you could show me just to understand how it's meant to work? (I have never done anything with DLL files specifically.)
Specifically, I'm just messing around - I don't have a goal in mind other than wanting to add functionality when AGS's code seems limited, and just to know how they work. I am trying to make a run-time engine plugin as the first thing.
Yes, you need only agsplugin.h, and you don't need any other files. agsplugin.h contains declaration of the engine's API. The latest one may be found here:
https://github.com/adventuregamestudio/ags/blob/master/Engine/plugin/agsplugin.h
I wish we had a template project for the plugin, but we still don't. I might make one later in a separate repository.
You may check out one of the existing plugins, for example here's my "sprite video" plugin:
https://github.com/ivan-mogilko/ags-spritevideo
although it may be overcomplicated for an example.
The minimal necessary files are:
agsplugin.h
ags_spritevideo.cpp - contains standard plugin callbacks (AGS_EngineStartup, AGS_EngineShutdown, etc) and DLLMain for Windows DLL
EditorPlugin.cpp - contains callbacks for the Editor, which generate plugin's script header (necessary for scripts to compile).
You may organize your plugin differently. It does not matter which *files* are there in the project, but rather which standard callbacks are included in those files, because that's what editor and engine will be looking for.
Trying to learn from huge projects without explanations overwhelms me, but I'll try. I don't quite understand the bare minimum that needs to be included in a plugin for it to work.
Quote from: Kara Jo Kalinowski on Tue 18/02/2025 04:53:04Trying to learn from huge projects without explanations overwhelms me, but I'll try. I don't quite understand the bare minimum that needs to be included in a plugin for it to work.
You do not need to check the whole project, only 3 files that I've mentioned.
The bare minimum for plugin to be loaded by the engine is function "int AGS_PluginV2()", which must be present and return anything except 0.
int AGS_PluginV2()
{
return 1;
}
For DLL to be compiled for Windows there has to be "DllMain", which again does not have to do anything, just return TRUE.
https://learn.microsoft.com/en-us/windows/win32/dlls/dllmain
Anything beyond that is required if you need plugin to do something specific.
(https://i.imgur.com/0nXzvm7.png)
(https://i.imgur.com/p7E3gol.png)
What is all of the things I have to export from the plugin to stop getting errors? Just this doesn't work:
#include <Windows.h>
int AGS_PluginV2()
{
return 1;
}
// DllMain - standard Windows DLL entry point.
// The AGS editor will cause this to get called when the editor first
// starts up, and when it shuts down at the end.
BOOL APIENTRY DllMain(HANDLE 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;
}
I don't really want to keep solving this one error at a time until it stops erroring... I don't understand. I need a starting point. I had tried some other code that chatgpt gave me and it wasn't completely solving my issues, I thought I might be missing a dependency or something. Anyways, I'm too tired to understand this now, if nothing else, I'll keep trying tomorrow.
Looks like I forgot about AGS_GetPluginName. This is required for the Editor.
Why using ChatGPT when I gave you a link to a working plugin source?
Here are the functions which are exported for the Editor by my plugin, which I linked previously:
https://github.com/ivan-mogilko/ags-spritevideo/blob/46b34f4470156f48f4c8ae0f8b865d167166af49/ags_spritevideo/EditorPlugin.cpp#L102-L149
I cannot tell much about the second error. It depends on which configuration and which MSVS you are building.
Perhaps, try building in Release configuration before testing: Debug configuration usually links some extra dependencies.
I'm really trying here, but I can't figure out how to make sure those functions get exported. I included the code from those files you mentioned. I need to include Common.h, all of Common.h's dependencies, and so on? I tried using the console and it doesn't appear to be exporting any functions. I don't know what code causes the functions to be exported.
agsplugin.h has this:
DLLEXPORT const char * AGS_GetPluginName(void);
EditorPlugin.cpp has
LPCSTR AGS_GetPluginName()
{
// Return the plugin description
return "SpriteVideo Plugin";
}
Again, I've not worked with DLL files, my brain isn't good at reading code I've never worked with and understanding it without explanations.
I just want to make something simple showcasing how information is passed back and forth between the DLL such as AGS reading the result of a function which returns "Hello, world" and similarly a function accessing some data within AGS using the DLL.
Quote from: Kara Jo Kalinowski on Tue 18/02/2025 16:47:17I'm really trying here, but I can't figure out how to make sure those functions get exported. I included the code from those files you mentioned. I need to include Common.h, all of Common.h's dependencies, and so on? I tried using the console and it doesn't appear to be exporting any functions. I don't know what code causes the functions to be exported.
I don't understand anything you've just said. Export what functions? What is "Common.h"? Which console?
Quote from: Crimson Wizard on Tue 18/02/2025 17:06:27Quote from: Kara Jo Kalinowski on Tue 18/02/2025 16:47:17I'm really trying here, but I can't figure out how to make sure those functions get exported. I included the code from those files you mentioned. I need to include Common.h, all of Common.h's dependencies, and so on? I tried using the console and it doesn't appear to be exporting any functions. I don't know what code causes the functions to be exported.
I don't understand anything you've just said. Export what functions? What is "Common.h"? Which console?
-The first error message. AGS_GetPluginName not exported from plugin. What is exporting it from the plugin? I've included all the code related to AGS_GetPluginName and nothing is being exported from the plugin.
(https://i.imgur.com/AxMRuuK.png)
Seems to show no functions are being exported.
EditorPlugin.cpp has an include "Common.h" but if I comment that out, it builds.
I have
EditorPlugin.cpp https://pastebin.com/GTERQdXu (commenting out the Common.h include)
agsplugin.h https://pastebin.com/N9GDp2m5
dllmain.cpp
#include <Windows.h>
#include "agsplugin.h";
#include "EditorPlugin.cpp";
int AGS_PluginV2()
{
return 1;
}
// DllMain - standard Windows DLL entry point.
// The AGS editor will cause this to get called when the editor first
// starts up, and when it shuts down at the end.
BOOL APIENTRY DllMain(HANDLE 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;
}
I am missing something fundamental and I don't know what I am missing, because I don't know it.
Right, so you need to declare one compiler macro: THIS_IS_THE_PLUGIN.
In which case DLLEXPORT macro will become properly defined when you compile DLL, and functions become exported AFAIK.
You may either do
#define THIS_IS_THE_PLUGIN
before including "agsplugin.h"
or add THIS_IS_THE_PLUGIN to the Preprocessor Definitions in the project settings.
EDIT: I don't know why, but this is not explained in the manual.
Actually, nothing is explained in the manual.
Quote from: Crimson Wizard on Tue 18/02/2025 17:20:39Right, so you need to declare one compiler macro: THIS_IS_THE_PLUGIN.
In which case DLLEXPORT macro will become properly defined when you compile DLL, and functions become exported AFAIK.
You may either do
#define THIS_IS_THE_PLUGIN
before including "agsplugin.h"
or add THIS_IS_THE_PLUGIN to the Preprocessor Definitions in the project settings.
Thank you, that worked. For the second error...
I am using x86 release. The only thing I changed in the settings was turning precompiled headers off. VS 2022 free
When a C or C++ program is built with MSVS, it will require corresponding VC runtime redistributable installed on the system. This depends on the selected Windows SDK and platform toolset (these may be found in project settings).
Supposedly, if you're using VS 2022, then you may use the generic VC redist for 2015-2022 versions, found here:
https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version
Quote from: Crimson Wizard on Tue 18/02/2025 17:59:45When a C or C++ program is built with MSVS, it will require corresponding VC runtime redistributable installed on the system. This depends on the selected Windows SDK and platform toolset (these may be found in project settings).
Supposedly, if you're using VS 2022, then you may use the generic VC redist for 2015-2022 versions, found here:
https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-microsoft-visual-c-redistributable-version
I have both the 64 bit and x86 versions installed. The dependencies listed here I have confirmed are in windows/system32 or a subfolder. I am compiling this DLL for x86 since AGS is 32-bit, I believe.
(https://i.imgur.com/RlzDE77.png)
Well, I cannot tell what may be the problem without seeing the project or dll.
My plugin's dll has only 2 dependencies according to dumpbin: kernel32.dll and user32.dll.
Although I compiled it with VS 2015.
https://github.com/karajokalinowski/agsTest but compiled with VS 2022
Well, it works for me. And the dummy plugin that I made in VS 2019 right now also has exact same dependencies:
https://github.com/adventuregamestudio/ags-demo-plugins/
Which version of AGS do you have installed on your computer right now?
Have you tried installing VC Redist 2015-2022 that I linked above?
AGS Editor .NET (Build 3.6.1.25)
I installed both the 64 and 86 versions of the thing you linked above.
Actually, I tried it in 4.00.00.14 and it works there.
Actually never mind... I forgot to delete an older version of the DLL... I didn't realize which DLL it was giving me problems about :/
Okay, now to try and figure out how to actually make something. Thanks
When distributing games made with plugins do I also need to distribute the visual c libraries?
I was not thinking clearly lately.
There are two ways to build a C++ program in MSVS:
- dynamically linking runtime VC libs; this means that the program expects them to be installed in the system;
- statically linking runtime VC libs; this means that the program will be linked with necessary libs at build time.
Engine does the latter, that's why you don't have to install these VC redist libs along with the games.
So you can do the same with plugins.
This is done by going into project properties:
-> C/C++
-> Code Generation
-> Runtime Library
=> set it to
* for Release config: Multi-threaded (/MT)
* for Debug config: Multi-threaded Debug (/MTd)
And rebuild. Then it should not require any extra installations at a cost of DLL becoming somewhat bigger.
I added this to the ourScriptHeader in EditorPlugin.cpp
"import const char* HelloWorld();\r\n"
Then this in the .cpp file
const char *HelloWorld() {
return "Hello World";
}
void AGS_EngineStartup(IAGSEngine* lpEngine) {
engine = lpEngine;
engine->RegisterScriptFunction("HelloWorld", (void*)HelloWorld);
}
At first I tried just the cpp file stuff but the editor wasn't recognizing the HelloWorld function. Adding the other line allowed the editor to recognize the function
Line 59: Display(HelloWorld());
__Plugin100.ash(59): Error (line 59): Cannot create pointer to basic type
What am I doing wrong? Thanks.
There's no such thing as "const char*" in AGS script. You need to use String type, which is a string class.
In plugin you will have to call IAGSEngine.CreateScriptString in order to create the string object that you can return.
Example:
"import String HelloWorld();\r\n"
const char *HelloWorld() {
return engine->CreateScriptString("Hello World");
}
You could take a look at the Clipboard plugin, which also has to do the conversion to and from AGS strings. (Though note that it has not been updated to support Unicode strings.)
https://github.com/messengerbag/Clipboard
The important bits are:
const char *ourScriptHeader =
"#define CLIPBOARD_PLUGIN\r\n"
"#define CLIPBOARD_PLUGIN_VERSION 0.04\r\n"
"/// Methods to access the Windows clipboard (via AGS Clipboard Plugin)\r\n"
"builtin struct Clipboard {\r\n"
" /// Paste a String from the clipboard. Returns null if not available\r\n"
" import static String PasteText ();\r\n"
" /// Copy a String to the clipboard. Returns true if successful\r\n"
" import static bool CopyText (String copyString);\r\n"
"};\r\n";
const char* Clipboard_PasteText(void) {
HGLOBAL hglb;
LPTSTR lptstr;
const char* pasteString = nullptr;
if (!IsClipboardFormatAvailable(CF_TEXT))
return nullptr;
if (!OpenClipboard(engine->GetWindowHandle()))
return nullptr;
hglb = GetClipboardData(CF_TEXT);
if (hglb != nullptr)
{
lptstr = reinterpret_cast<LPTSTR>(GlobalLock(hglb));
if (lptstr != nullptr)
{
pasteString = engine->CreateScriptString(lptstr);
GlobalUnlock(hglb);
}
}
CloseClipboard();
return pasteString;
}
void AGS_EngineStartup(IAGSEngine *lpEngine) {
engine = lpEngine;
// Make sure it's got the version with the features we need
if (engine->version < 3) {
engine->AbortGame("Engine interface is too old, need newer version of AGS.");
}
engine->RegisterScriptFunction("Clipboard::PasteText", Clipboard_PasteText);
engine->RegisterScriptFunction("Clipboard::CopyText^1", Clipboard_CopyText);
}
This adds this header to AGS, and hooks up the methods (I've omitted Clipboard.CopyText) to the corresponding plugin functions:
#define CLIPBOARD_PLUGIN
#define CLIPBOARD_PLUGIN_VERSION 0.04
/// Methods to access the Windows clipboard (via AGS Clipboard Plugin)
builtin struct Clipboard {
/// Paste a String from the clipboard. Returns null if not available
import static String PasteText ();
/// Copy a String to the clipboard. Returns true if successful
import static bool CopyText (String copyString);
};