mono / CppSharp

Tools and libraries to glue C/C++ APIs to high-level languages
MIT License
3.15k stars 518 forks source link

Constructor/delegate mapping? #1837

Open mitchcapper opened 8 months ago

mitchcapper commented 8 months ago
Brief Description

Love CppSharp compared to the alternatives. Was my first time using it and tested it on something small. I am pretty sure I am abusing CppSharp in ways one shouldn't as I didn't see most of the other generators using it doing similar. Still it was able to do some magical mapping. I am sure this may be in part due to #984 as I already rename several things to make CppSharp 'discover' the class possibility (and declare a fake typedef).

One item I wasn't able to figure out was how to change a C function to a constructor for the class I forced.

Here is my attempt to build it from scratch: https://github.com/mitchcapper/WebUIAutoBuild/blob/master/CodeGen/WebUIGenerator.cs#L114-#L133

I was able to call the static method WebUI.NewWindow just unable to turn it into a constructor (through CPPGen clearly able to write that myself as in: https://github.com/mitchcapper/WebUIAutoBuild/blob/master/WebUILib/WebUIClassAdditions.cs#L8-L10 ).

Here is the original C-header: https://github.com/webui-dev/webui/blob/55e38e89cec3fee18432e19ff4401c9e23c2ef36/include/webui.h

the https://github.com/mitchcapper/WebUIAutoBuild does have the complete code used.

One other item somewhat related to method generation and likely related to #1726 was trying to get CppSharp to wrap a function pointer that had an arg of one of the classes. I verified it was reading the type correctly, but even when I tried to manually force the type at different points it eventually always got changed to an IntPtr. I added a typedef for a delegate which made it a bit more clear what it was for (even if the delegate still just took an intptr).

Generating the wrapper though is quite generic but would involve changing the actual delegate passed to the caller and then calling the GetOrCreateInstance. Example https://github.com/mitchcapper/WebUIAutoBuild/blob/master/WebUILib/WebUIClassAdditions.cs#L18-L21 .

It is quite possible both these things are doable with CppSharp and I just missed how. Most of the items I figured out through the debugger attached to manually written C code to see what CppSharp was expecting to get the desired c#.

tritao commented 8 months ago

Hello, abusing CppSharp is certainly the way to go haha, its to be used as a flexible toolkit. There is always lots of customization and pain when buildings bindings.

About the first item, guess we don't have anything specific yet for that kind of use case, but seems like it would be an useful addition. Its specific enough that we would probably need to special case it in the C# generator, maybe by flagging the method or class somehow (MethodInstanceKind, or something like that). Unless you have a ton of cases, having some partial additions is easy enough though. But happy to accept a PR with a more automated solution, if you feel like it.

About the second item, seems certainly related to #1726 as you identified. Don't really have time to look into all of the specifics, but sounds like the same issue. I don't think this one would be that hard to fix, but again, unless you have a lot of callbacks, might be easier to use the same approach as before and build some hand maintained high level wrappers.

Also that's a pretty cool project! I've have some fun working on something similar myself for buildings apps with web GUIs, though I was binding wxWidgets webview APIs.

mitchcapper commented 8 months ago

Unless you have a ton of cases, having some partial additions is easy enough 100% this was more of me just seeing what cppSharp could do on a small footprint API. Without a doubt neither item was complex to work around. I wasn't sure if there was some naming that would have caused it to turn into the constructor but I am assuming it needs a proper c++ constructor (given the main focus of the library).

for reference for anyone else: here was the simple partial constructor that seemed like the right way to go

public Window() {
            __Instance = new __IntPtr(__Internal.WebuiNewWindow());
            __RecordNativeToManagedMapping(__Instance, this);
        }

About the second item

Yes easy enough to do a wrapper as well. I'll look a bit more as the CPP internals to see about transforming it into a run that could work.

public ulong Bind(string element, WrappedWebEventHandler func) { 
            WebEventHandler customDel = (__IntPtr evt) => func(WebUIEvent.__GetOrCreateInstance(evt));
            return Bind(element, customDel);
        }
        public delegate void WrappedWebEventHandler(WebUIEvent evt);

Yeah WebUI was pretty new to me. It is so exceptionally light weight with no requirements other than one of many browsers on the system, it is an innovative approach. It is very sparse in the api but it's pretty easy to wrap the JS comms back and forth pretty well and with that it can be quite capable given the span of what JS can do.

@Juff-Ma has put together a great project at https://github.com/Juff-Ma/WebUI.NET my goal here was just a test for that for seeing if it was something that could be automated, and at the same timed coerced into a more standard c# format (which CppSharp 100% was great at).