Asterisk depends on quite a few structures, obviously :). One of my goals for ast_mono is to make the API seem as .NET-friendly and standard as possible. This includes creating a real object oriented API, rather than the C way (where you pass the structure in as the first parameter). At runtime it'll be nearly the same thing, but it really changes the whole of the API.Before I can do any real function calls or library work, I need to have the base classes defined: channels, files, etc. My first approach was the “nicest”. My idea was to prototype the structures in C#, allowing direct access from the .NET runtime to the structure, using C# unsafe code (i.e., ast_channel *myPtr; myPtr->language). I'd rolle the unsafe code inside the class, so to an end-user, it'd appear as a normal property. However, I don't trust that all the structures in Asterisk will stay the same all the time. If a field was added or moved around, I'd have to declare a whole different prototype. To make things worse, I think it's entirely possible that there could be some #defines that people change per-platform, and that there could be multiple valid prototypes that I'd need to support (as part of the C# build process). My goal is to ship a runtime that can be built on the target machine, but the C# API should be able to be distributed in binary form without any issues. One main goal of this is that building ast_mono won't require a C# compiler. The IL binaries should be fully portable by themselves.So, despite the advantages and elegancy of being able to access the structures with pure managed code, it's not going to happen. I checked out SWiG, and it's quite powerful. SWiG allows you to take C/C++ headers and turn them into definitions for C#, Java, Perl, and a slew of others. I might possibly be able to use this tool as a basis for my app. For C#, SWiG creates a class that takes a pointer to the unmanaged structure. Then it generates properties in C# that call P/Invoke methods on a C class it generates. So to access the language field of ast_channel, the get property accessor P/Invokes to ast_channel_get_language. This is OK. However, I believe it can be done better using internalcalls. Mono allows a runtime host to register internalcalls. Internalcalls run as part of the runtime, and have access to the native .NET types. This removes the need for marshalling to those calls: a big plus. Obviously there will still be some marshalling needed for some types (i.e. taking a null-terminated ANSI string and creating a .NET string), but it'll be easier to work with. For the performance and flexibility of doing things this way, I think it's worth the bit of extra work to write a small program to generate some of the wrapper code for me instead of using SWiG. (I also am not very fond of the code generated by SWiG.) Also, I should be able to grab the comments from the headers and generate some basic XML docs.Methods are quite a bit simpler, with the same basic principles applying. I'll extend my code to emit some basic definitions (C# prototypes + basic C Mono implementations) and that should get me going. On a side note, although right now I'm sticking to the ISO spec of C#, Mono 1.2 has support for many of Whidbey's features. This means I get to use generics soon. Also, I am going to be compiling with the Whidbey C# compiler, so compile-time only features, such as partial classes, are available too. Yum :).
Remember Me