ANSI C as the core of a C # project? Is it possible?

I am writing a NON-GUI application that I want to be cross-platform between OS X and Windows. I look at the following architecture, but I don't know if it will work on the window side:

(entry point to a specific platform) → ANSI C main loop => ANSI C model code that performs data processing / logic => (special assistants for the platform)

So, the main material that I plan to write in standard ANSI C, because A) it must be platform independent, B) I am very comfortable with C, C) It can do the job and do it well

(entry point to a specific platform) can be written in all necessary for the job, this is a small amount of code, it does not matter to me.

(Special assistants for the platform) is a sticky thing. It's like parsing XML, accessing databases, toolkit stuff for graphics, whatever. Things that aren't easy in C. Things that modern languages ​​/ frameworks provide for free. On OS X, this code will be written in Objective-C interaction with Cocoa. On Windows, I find it best to use C #

So on Windows my architecture (simplified) looks like

(C # or C?) → ANSI C → C #

Is it possible? Some thoughts / suggestions so far ..

1) Compile my C-kernel as a .dll - this is fine, but there seems to be no way to call my C # helpers if I cannot somehow get pointers to functions and pass them to my kernel, but this seems unlikely

2) Compile C.exe and C # .exe and ask them to talk through shared memory or some kind of IPC. I'm not completely against this, but it obviously introduces a lot of complexity, so it doesn't seem perfect

3) Instead of using C # C ++, it gets me good data for data management and good helper code. And I can mix it easily. And the work I'm doing can probably be easily ported to Linux. But I really don't like C ++, and I don't want this to be included in a third-party festival library. Not that it was a huge deal, but in 2010, everything you need for basic data management should be built-in. And focusing on Linux is really not a priority.

Note that no “total” alternatives are in order, as suggested in other similar SO issues I have seen; java, RealBasic, mono .. this is an extremely efficient application that executes soft real time for games / simulations, I need C and friends here to do it right (maybe you won’t, but I)

+4
source share
5 answers

First of all, to answer one specific question: you can assign delegates as function pointers to your own C code - in fact, it “just works”, and P / Invoke takes care of all the wrappers:

// C# class ManagedEntryPoint { [DllImport("core", CallingConvention=CallingConvention.Cdecl)] static extern void NativeEntryPoint(Func<int, int, float> helper); static float Helper(int, int) { ... } static void Main() { NativeEntryPoint(Helper); } } // C void NativeEntryPoint(float (*helper)(int, int)) { float x = helper(1, 2); ... } 

However, I do not see much point in this - it is easier to use the C ++ / CLI compiler. Please note that this does not mean that you really need to use C ++ - you can stick with a subset of C compatible with C ++, which is 95% of it (I would expect the only thing you would need to do differently on practice clearly throws malloc returns). You compile your own C functions as native .libs, and then link them to an executable compiled with /clr . C ++ / CLI will take care of all marshaling, and you won’t need to write P / Invoke declarations, etc.

+1
source

Short answer: Yes. You can easily access unmanaged .NET code, but you have to marshal your data.

Long answer: Do not do this. Do you know about a monoproject ? This is an x-platform implementation of .NET. They are slightly behind Microsoft, but they still offer a solution that works for many. I would highly recommend keeping managed code, if at all possible, you defeat the goal of .NET if you enter and exit C code. It will also help reduce the complexity of your project by ten times.

If you need C ANSI to access at a low level, I suggest you demonstrate a small and tested C ANSI api for your .NET kernel to do any low-level.

C # Core <==> ANSI Small C Helper Library

+6
source

Why don't you do all this in C ++? You can hit all of your platforms and get everything that you say C does not have. C # - only for clean dot objects, c / C ++ still works on windows, just get the api call you need for everything you are trying to do.

+1
source

I like the answer of Aren (see Mono), but if you really want to use C + C #, you can use SWIG to create wrappers of C code somewhat automatically. He got a learning curve, but if the number of C functions you want to call from C # is large enough, it's worth the effort. SWIG does not support Objective-C out of the box, but there is a branch with incomplete support for it.

Update: oh, you want, first of all, to call C # from C? Sorry, SWIG is not really designed for this. However, C # allows this. You can use a C # or C / C ++ entry point (C # entry point is probably simpler), and you can pass pointers to C # functions (delegates) in C code.

Suppose you want to pass the void (string) function from C # to C. At first I don’t know how C code can directly get pointers to C # functions (maybe I just don’t know how.) Instead, I would start the program in C # code and got C # code for C code.

Something like that:

 // Visual C code: // (.NET functions use the __stdcall calling convention by default.) typedef void (__stdcall *Callback)(PCWSTR); void __declspec(dllexport) Foo(Callback c) { c(L"Hello world"); } // C# code: // (A delegate declaration can include marshaling commands that // control how argument types are converted.) public delegate void Callback([MarshalAs(UnmanagedType.LPWStr)] string message); void PrintOut(string message) { Console.WriteLine(message); } 

Here we have the C function "Foo", which can get a pointer to the C # function "PrintOut" (or the C function, for that matter), and also type typedef. We use __declspec (dllexport) so that C # code can call it.

On the C # side, there is a delegate declaration, which is roughly the same as typedef in C and the PrintOut function that we want to pass to C.

Assuming you compile your C code into a DLL called Foo.dll, you will need a C # P / Invoke declaration and code that actually calls Foo:

 [DllImport("Foo")] public static extern void Foo(Callback c); public void CallFoo() { Foo(PrintOut); } 

The above will probably work first, but there is one "gotcha": the above code wraps the PrintOut in the delegate, and the garbage collector will eventually free the delegate if you don't keep a link to it. Therefore, if you want the C code to have a permanent link to the C # method, we must change the above C # code to keep the delegate link:

 [DllImport("Foo")] public static extern void Foo(Callback c); static Callback PrintOutRef; // to prevent garbage collection of the delegate public void CallFoo() { Foo(PrintOutRef = PrintOut); } 

Hope this helps!

+1
source

There is no reason to use ANSI C on top of C ++. In addition, if you have C ++ code, writing a C ++ / CLI shell for use in C # is very trivial (as far as I know), and C ++ will not add two floats more slowly than C (many others operations are actually faster, like sorting). In addition to this, C ++ is pretty flexible on what you can do with it.

C ++ ↔ C ++ / CLI ↔ C # is probably the easiest way, since C ++ / CLI interoperability can easily work in both directions.

0
source

Source: https://habr.com/ru/post/1312986/


All Articles