Purely proof-of-concept at the moment. Barely anything besides registering new script functions has been tested.
Website (http://bitbucket.org/tbohnen/agspluginsharp)
The 'AGSPlugin' class contains the callback methods as described here (http://www.adventuregamestudio.co.uk/acplugin.htm).
RegisterScriptFunction example:
Declare a method:
private static int AddNumbers(int a, int b)
{
return a + b;
}
and a matching delegate:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int AddNumbersDel(int a, int b);
The delegate has to use the UnmanagedFunctionPointer attribute with CallingConvention.Cdecl.
Register the script header in EditorStartup:
public int EditorStartup(IAGSEditor editor)
{
editor.RegisterScriptHeader("import int AddNumbers(int, int);
");
return 0;
}
Register the script function in EngineStartup:
private AddNumbersDel del;
public void EngineStartup(IAGSEngine engine)
{
del = new AddNumbersDel(AddNumbers);
IntPtr address = Marshal.GetFunctionPointerForDelegate(del);
engine.RegisterScriptFunction("AddNumbers", address);
}
AGS plugins in C#?
you are a fucking beautiful man and I offer kisses and snuggles in payment.
This is brilliant, I wanted to do the same thing but you beat me to it, and I'm happy you did! :D
As a c# lover and c++ hater, I thank you!
Wow, that's pretty damn interesting. Still not sure it would be a good idea for me to use XNA because of the iffy licensing, but at least this makes it possible. Would there be any considerable slowdowns in using the wrapper compared to straight C++?
i dont think the XNA library is used.. its just C#
No, I meant now that C# can be used by plugins, linking to XNA is suddenly an option - one I had previously discarded while searching for appropriate libraries and engines. (Not sure there would be much to gain by using it as an AGS plugin rather than building the entire game in XNA, but I was impressed with some of the 2D capabilities of the framework - including totally neat realtime lighting).
ahh that makes sense.. I didnt think you were that stupid :P
YAI!
New version is up.
-Fixed 'AGS_EditorSaveGame' and wrongly marshalled char pointers.
-Most constants are now enums.
-Most properties are now PascalCased.
Quote from: GarageGothic on Thu 22/07/2010 16:01:19
Would there be any considerable slowdowns in using the wrapper compared to straight C++?
There's a significant overhead involved in calling the AGS API methods.
However, I haven't made any performance tests yet.
this doesn't seem to compile in c# express.
its requests ilasm.exe which i believe is part of the vs tools and so is not part of the express edition.
is there any way to make it compile in express?
Install the .NET SDK:
32 bit:
http://www.microsoft.com/downloads/details.aspx?FamilyID=fe6f2099-b7b4-4f47-a244-c96d69c35dec&displaylang=en
64 bit:
http://www.microsoft.com/downloads/details.aspx?familyid=1AEF6FCE-6E06-4B66-AFE4-9AAD3C835D3D&displaylang=en
ok now i can get it to compile but AGS throws an unresolved import error and i can't see my error.
I pretty much copied your example verbatim so it must be something pretty basic.
Please try the updated example.
The error might be caused by the delegate getting GCed.
nope same problem,
heres my code for clarity:
namespace AGSPluginSharp
{
using System;
using System.Runtime.InteropServices;
public class AGSPlugin
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int AddNumbersDel(int a, int b);
#region Constructors
public AGSPlugin()
{
}
#endregion Constructors
#region Properties
#region Public Properties
public string Name
{
get
{
return "C# AGS Plugin";
}
}
#endregion Public Properties
#endregion Properties
#region Methods
#region Public Methods
public void EditorLoadGame(byte[] buffer)
{
}
public void EditorProperties(IntPtr parentHandle)
{
}
public byte[] EditorSaveGame(int maxBufferSize)
{
return new byte[0];
}
public void EditorShutdown()
{
}
public int EditorStartup(IAGSEditor editor)
{
editor.RegisterScriptHeader("import int AddNumbers(int, int);\r\n");
return 0;
}
public int EngineDebugHook(string scriptName, int lineNum, int reserved)
{
return 0;
}
public void EngineInitGfx(string driverID, System.IntPtr data)
{
}
public int EngineOnEvent(EventType evnt, int data)
{
return 0;
}
public void EngineShutdown()
{
}
private AddNumbersDel del;
public void EngineStartup(IAGSEngine engine)
{
del = new AddNumbersDel(AddNumbers);
IntPtr address = Marshal.GetFunctionPointerForDelegate(del);
engine.RegisterScriptFunction("AddNumbers", address);
}
private static int AddNumbers(int a, int b)
{
return a + b;
}
#endregion Public Methods
#endregion Methods
}
}
Do you have the VC++ 2010 redist installed?
http://www.microsoft.com/downloads/details.aspx?FamilyID=a7b7a05e-6de6-4d3a-a423-37bf0912db84&displaylang=en
Also copy PluginAPIWrapper.dll to the game's "_Debug" folder, or include the AGS editor folder in PATH.
yep i have the redist package and i'd already copied the wrapper over.
I've uploaded a new version which might fix the problem.
Calin, did that eventually work?
I havent got around to testing it yet.
The plugin i'm working on is coded in C++ since i need it to be fast.
Interesting!
Of course, you need to bear in mind that if you make a game that uses a C# plugin, then the player will need to have the .NET Framework installed in order to play your game.
Not much of an issue for windows users.
Quote from: Monsieur OUXX on Tue 03/08/2010 15:32:38
Calin, did that eventually work?
Works super for me (eventually) :D
Expect a small demonstration plugin soon...
Alright, back in the original post for this topic is the following:
"Register the script function in EngineStartup:
private AddNumbersDel del;
public void EngineStartup(IAGSEngine engine)
{
del = new AddNumbersDel(AddNumbers);
IntPtr address = Marshal.GetFunctionPointerForDelegate(del);
engine.RegisterScriptFunction("AddNumbers", address);
}
Where in the world is IAGSEngine?! I have AGS Types but IAGSEngine is not in there. Is my AGS broken?
i'm not sure what you mean...
in the code you posted 'engine' is an instance of the IAGSEngine class which is passed from the wrapper.
Yes. I know that, but it is not accepting it. I have VS C# 2008 and am "using AGS.Types;" but when I try to compile with IAGSEngine anywhere in my code, it crashes and says I am missing a directive.
Did you use the given template?
It's under Wrapper\Swig\IAGSEngine.cs
Small update:
The C++ glue code is included in the zip file.
PluginAPIWrapper.dll is compiled with MinGW, so you don't need the VC++ 2010 redist anymore.
Hi there,
I'm trying to return a String from a function.
First I just tried to return a C# string - kaboom... it crashed
Then I thought wait.. return a CreateScriptString(mystring) - kaboom...
Then I thought wait... the IAGSEngine and agspluginPINVOKE might be wrong with the return type,
so I've changed them from "string" to "IntPtr" and still - kaboom...
I thought maybe "IntPtr" is not "real" enough as a const char*, so I've changed all to "void*" (in usafe context),
and guess what? yeah... - kaboom
so.. smiley or anybody else.. PLEAAAASSSEEEE does someone knows how to return a string from c# ?
Thanks!!!!!!!!!!!!!!
You can take a look at the code I wrote for c# runner (the source code is in that thread), there are some functions there that return a string.
Thanks Tzachs!
The C# Runner link appears to be dead, could you repost?
Alternatively, could you give me the short version answer?
Thanks!!
p.s.
any idea on how to access the new ags features from the plugin? (i.e. new audio stuff and attributes)
Thanks for the heads up, I re-uploaded it to here (http://shutupload.com/dl/ca89554270b7/).
As for the short version answer, I don't have something special to offer here, cause I don't remember doing anything different for strings that I didn't do for the other types, if was pretty straight forward.
You're probably missing something simple, so I would compare my code to yours and see what's different...
Also, regarding the new audio, my guess is that the API doesn't have that functionality, so no way to access it. However since the source code of the editor is available (and in c#), you can possibly modify it to access the audio somehow, though I'm not sure how much work it will take.
tzachs, sorry for the long delay!
Your example is working alright, but the return type is actually derived from using the:
private static TOut CSRun<TIn, TOut>(TIn value, string className)
method (CSRunStringToString...)
Could you PLEASE verify a pure in-code string return type and let me know?
BIG THANKS!
The CSRun is only a generic method to run delegates, it's an inner implementation and have no effect of the API, I could have easily replaced that call with a simple:
return "hello world";
This would have worked all the same (guaranteed, this was the first thing I tried when I started playing with smiley's api).
Does anyone still have the C# wrapper? I tried all three of the links that I saw going to the file and they are all dead links. Please someone still have this. :)
Just send smiley a PM (http://www.adventuregamestudio.co.uk/forums/index.php?action=pm;sa=send;u=6032).
He was last active in July, he's still around it seems.
Link updated.