AGS Plugin API for C#

Started by smiley, Thu 22/07/2010 15:29:20

Previous topic - Next topic

smiley

Purely proof-of-concept at the moment. Barely anything besides registering new script functions has been tested.

Website

The 'AGSPlugin' class contains the callback methods as described here.

RegisterScriptFunction example:
Declare a method:
Code: ags

private static int AddNumbers(int a, int b)
{
   return a + b;
}

and a matching delegate:
Code: ags

[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:
Code: ags

public int EditorStartup(IAGSEditor editor)
{
   editor.RegisterScriptHeader("import int AddNumbers(int, int);
");
   return 0;
}

Register the script function in EngineStartup:
Code: ags

private AddNumbersDel del;
public void EngineStartup(IAGSEngine engine)
{
   del = new AddNumbersDel(AddNumbers);
   IntPtr address = Marshal.GetFunctionPointerForDelegate(del);
   engine.RegisterScriptFunction("AddNumbers", address);
}




Calin Leafshade

AGS plugins in C#?

you are a fucking beautiful man and I offer kisses and snuggles in payment.

tzachs

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!

GarageGothic

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++?

Calin Leafshade

i dont think the XNA library is used.. its just C#

GarageGothic

#5
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).

Calin Leafshade

ahh that makes sense.. I didnt think you were that stupid :P

Wonkyth

"But with a ninja on your face, you live longer!"

smiley

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.

Calin Leafshade

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?


Calin Leafshade

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.

smiley

Please try the updated example.
The error might be caused by the delegate getting GCed.

Calin Leafshade

nope same problem,

heres my code for clarity:

Code: ags

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

 




    }
}

smiley

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.

Calin Leafshade

yep i have the redist package and i'd already copied the wrapper over.

smiley

I've uploaded a new version which might fix the problem.

Monsieur OUXX

Calin, did that eventually work?
 

Calin Leafshade

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.

Monsieur OUXX

 

SMF spam blocked by CleanTalk