5

I have a legacy code implemented in C (not C++). I would like to be able to call a few methods in this C code from my C# code (on Windows). What would be the best approach to interface between the two language? Please note that the method in C is not stateless. We need to call two methods:

  1. initialization() => this will initialize the data structure and load data from files into memory. This method will be called once.
  2. ComputeSomething(parameters) => there will be several calls from C# to this method.

Note: These two methods actually call several other methods but these are only the two methods that we would like to expose to C# (the code is quite complicated, that's why we do not want to port to C#)

I have been able to import the c code into visual studio and able to compile the code successfully. I know that we can probably implement the C code as windows service but I am looking for a solution that allow us to call C method from C# directly. Any pointers is highly appreciated! (is COM interop related to what I am looking to do?)

mwong
  • 87
  • 1
  • 6
  • why not implementing your methods on c#? – Luiscencio Jul 14 '10 at 22:10
  • What is the compiled output of your C code? If its a .dll and supports COM you should simply be able to do an "add reference" from Visual Studio and browse to the dll file. – Nate Jul 14 '10 at 22:13
  • 1
    If you haven't already done so, wrapping your functions in a COM co-class and using .NET/COM interop seems like too much work / overkill. I would simply put those two C functions in a DLL and access them with P/Invoke, as suggested by Jason Evans. – stakx - no longer contributing Jul 14 '10 at 22:14
  • @Luiscencio: these two c methods actually call several other c methods. The whole code is quite complicated but we want to expose only these two methods to C#. @Nate: it seem like the output is .dll, let me try if I can add references. – mwong Jul 14 '10 at 22:26

3 Answers3

10

Sounds like you can use P/Invoke for this. Check out this site for tips:

http://www.pinvoke.net/

Also, try searching SO for advice on P/Invoke and Google for

c# pinvoke calling c code

I don't have any technical examples at hand, but I have written some .NET code which called Win32 API's via P/Invoke. The tricky part is getting the method signatures correct when passing parameters. This might help you out there.

Jason Evans
  • 28,906
  • 14
  • 90
  • 154
  • Thanks for the answer! Do you know if P/Invoke would work for my situation where the method calls are stateful? (need to call initialize to load data before calling another method) Do the global variables stay in memory for the subsequent method call? – mwong Jul 15 '10 at 14:10
  • Hand on heart, I don't know. However, since the C code needs to be loaded into the address space of the .NET code and remain resident (not dynamically loaded each time), I would expect the values of the C code to remain the same. I'm afraid that's something you will need to experiment with. :( Let us know what you find out, and whether my logic is totally wrong! – Jason Evans Jul 15 '10 at 14:16
2

Recent version of Visual Studio allow you to write C++ code that can call unsafe functions but still interface with CLR managed code. They call this "Implicit PInvoke," or "C++/CLR." Check out the MSDN article "Using C++ Interop" to learn more.

Managed code can't call unmanaged directly, so you need wrapper functions to handle the memory management issues and to translate between .NET objects and the data structures of your application. From the link above, check out the section on "How to: Wrap Native Class for Use by C#."

Karmastan
  • 5,618
  • 18
  • 24
1

Here is a solution. The solution allows to call C# function from C by decorating your function with [DllExport] attribute (opposite of P/Invoke DllImport).

https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

C# code

class Test
{
     [DllExport("add", CallingConvention = CallingConvention.StdCall)]
     public static int Add(int left, int right)
     {
         return left + right;
     } 
}

C code

 int main()
 {
      int z = add(5,10);
      printf("The solution is found!!! Z is %i",z);
      return 0;
 }
MajesticRa
  • 13,770
  • 12
  • 63
  • 77