• entries
437
1000
• views
337160

# GameMonkey C API Anti-Wrapper

248 views

I'm reposting this from the GameMonkey forums as I think you guys will have some good opinions about it (being the awesome folks that you are).

One thing that GameMonkey (GM) currently lacks is the ability to be used via 'C' APIs (and languages which can support them directly from DLLs such as VB6, C#, Delphi, D, etc). This isn't a failing in my eyes, so I'm not being critical of GM's wonder API (which is infinitely better than Lua's); I'm merely looking for a way to ease the C# Wrapper I'm coding as well as perhaps broaden the GM audience a little. What I'm playing with is writing an anti-wrapper for GM (anti-wrapper is my own word :p).

For the anti-wrapper, we'd need to unwrap each GM class into structs (if data is public) or handles; and functions (which were previously member functions). So gmMachine::ExecuteString would have to be unwrapped to something such as gmMachine_ExecuteString, which would then take an object handle to a gmMachine object (to act as 'this'). Bear in mind that C APIs generally have warts, or library prefixes, to distinguish similar functions from different libraries. For this test, I'm looking at the warts gmcapi, or even just gmc.

Where we have a GM program that goes as follows:

gmMachine *gm = new gmMachine(); gm->ExecuteString( "global a = 1234; print( a );" ); gmTableObject *tab = gm->GetGlobals(); gmVariable v = tab->Get( gm, "a" ); v.m_value.m_int = 9876; tab->Set( gm, "a", v ); gm->ExecuteString( "print( a );" ); delete gm;

The same program in our unwrapped (and warted) API would look as follows:

gmc_gmMachine gm = gmc_gmMachine_New(); gmc_gmMachine_ExecuteString( gm, "global a = 1234; print( a );" ); gmc_gmTableObject tab = gmc_gmMachine_GetGlobals( gm ); gmc_gmVariable v = gmc_gmTableObject_Get( tab, gm, "a" ); v.m_value.m_int = 9876; gmc_gmTableObject_Set( tab, gm, "a", v ); gmc_gmMachine_ExecuteString( gm, "print( a );" ); gmc_gmMachine_Delete( gm );

Yes, the API looks a little noiser and is more verbose, but it works.

My main questions are regarding styling and naming conventions.

- Would the wart gmc_ or gmcapi_ be preferable to you?
- Should functions be cased as they are in the example above, or would you prefer C naming conventions such as:

gmc_gmMachine_ExecuteString
gmc_gmMachineExecuteString
gmc_MachineExecuteString
gmc_Machine_ExecuteString
gmc_Machine_Exceute_String
gmcMachineExecuteString
gmc_machine_execute_string

The last one is how I'd say the C world is used to APIs, but I think I'd prefer the first example. From there it's instantly clear which gm class it was taken from, and which function was used.

It all comes down to preference, I guess. which owuld you prefer to see/use if you HAD to use this API? (Not that many people will).

My main motivation behind this is so that I can use GM with VB6 at work, and use P/Invoke directly on this API via a DLL so that people can start using GM in C# and .NET.

Progress so far is that I've coded up the above example so it works; I stopped to ask this question so I didn't get too far down the wrong track and had to change the entire API for stylistic reasons :p

For your naming convention, consider your audience. Are you targetting C programmers who want to use Game Monkey, or are you targetting Game Monkey users who want to use C? If the former, use the style that matches existing c libraries. If the former, use the style that changes the names the least.

Quote:
 Original post by Deyja For your naming convention, consider your audience. Are you targetting C programmers who want to use Game Monkey, or are you targetting Game Monkey users who want to use C? If the former, use the style that matches existing c libraries. If the former, use the style that changes the names the least.

Well, I'd say both and neither. Bear in mind that yes, I'll be targetting C programmers but mainly VB and C# programmers too (ok C# will have an additional .NET P/Invoke wrapper over the top - wrapping a wrapper - heh).

My main concern is that when people read docs, or look at the existing C++ API, they will instantly know which functions map to which, rather than having to sit and contemplate the naming conventions. This is my primary reason for wanting to use the first style on this list; but at the same time I really don't want to alienate a whole potential userbase because "eww the API looks ugly".

Hmmm; I guess as long as I'm consistent, it doesn't really matter, right?

That comparison/example you posted reminds me of why I like C++ and its namespaces/organisation features [grin]

Quote:
 I guess as long as I'm consistent, it doesn't really matter, right?
Consistency is extremely important at the API-level in my opinion. However, I wouldn't go so far as "it doesn't really matter" - adding _oli_is_cool_ in every function name is consistent but not particularly useful [grin]

I dont personally like the use of underscores; when typing out a long sequence of letters I mis-type underscores much more often than anything else. Although that could just be me - I often end up typing ..DIRECT£D.. instead of ..DIRECT3D..

Something to consider, if you have it to hand, but the DirectX API is primarily object-oriented but it can also be consumed via pure C compilers. Digging around in the headers will find a slew of #define's remapping member functions directly via the vtbl (iirc) and generally messing around a bit. No idea if that'll work for GM, but it could be an idea.

Not sure if it'd be useful, but under VB6 you can "alias" imported DLL functions (used by Win32 to remap the ansi/unicode forms iirc). Thus you could set it up in VB6 so the programmer sees (and uses) friendly names but the real API is as fugly as you want [smile]

Jack

I prefer the third one:

gmc_MachineExecuteString

I don't see the need to over emphasize which library the function for executing a string came from, but I could get used to either one on the list.

By the way, I was also looking into GameMonkey scripting and I think that I prefer it over Lua for lite scripting support.

I finally settled for gmcMachineExecuteString

I'm working on the C# wrapper for my C wrapper (yes, I know it's complicated :P)

## Create an account

Register a new account