Forum guidelines
AuthorQuestion
Call C# code in C
Posted By sridevi pc on 30 Nov 2012
I want to call c# code in c is it possible if so give me simple example to multiply by calling c# multiply function from c

AuthorReply
Re: Call C# code in C
Posted By Vithal Wadje on 30 Nov 2012  
not possible madam, the compilers and envirment are different for both the languages and most important thing is that C# is  a object oriented language...
Vithal Wadje
Re: Call C# code in C
Posted By Vulpes on 30 Nov 2012  
Despite what Vithal said, it is possible to do this using a little known technique called reverse P/Invoke.

However, as the C# compiler doesn't support DLL exports directly, you have to create the C# dll, edit the IL to insert an .export directive for each method you want to export and then recompile the dll using a tool called ilasm.exe.

Also, as C knows nothing about objects, this will only work with static methods whose parameters and return types are simple types.

Although none of this is particularly difficult, it is rather messy so I'll try to describe each step in turn.

First, go into the Visual Studio command prompt, type: notepad multiply.cs, enter the following code and save it:

using System;

public static class Arithmetic
{
   public static int Multiply(int num1, int num2)
   {
      return num1 * num2;
   }
}


Now type the following at the command prompt to compile this into a .dll

csc /t:library multiply.cs


Next type this at the command prompt to extract the IL from the dll using ildasm.exe and put  it into a file called multiply2.il:

ildasm multiply.dll /out=multiply2.il

Next open multiply2.il in notepad and insert the line I've highlighted (which will cause the Multiply method to be available as a DLL export) and save it:


//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.1
//  Copyright (c) Microsoft Corporation.  All rights reserved.



// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly multiply
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module multiply.dll
// MVID: {2E01BB12-10AB-4E3A-9E16-6921ADAAAA0D}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x003D0000


// =============== CLASS MEMBERS DECLARATION ===================

.class public abstract auto ansi sealed beforefieldinit Arithmetic
       extends [mscorlib]System.Object
{
  .method public hidebysig static int32  Multiply(int32 num1,
                                                  int32 num2) cil managed
  {
    .export [1] as Multiply  
    // Code size       9 (0x9)
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  ldarg.1
    IL_0003:  mul
    IL_0004:  stloc.0
    IL_0005:  br.s       IL_0007

    IL_0007:  ldloc.0
    IL_0008:  ret
  } // end of method Arithmetic::Multiply

} // end of class Arithmetic


// =============================================================

// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file multiply2.res


Now recompile the dll (as multiply2.dll) using ilasm.exe by typing the following line at the command prompt:

ilasm /DLL multiply2.il

Next, open notepad to create a C file (test.c say) to import and call the Multiply function from the C# dll, and save it:

#include <windows.h>

typedef int (*MyFunc)(int, int); /* define function pointer to call function in dll */

int main()
{
   int result;
   MyFunc multiply; /* declare variable of function pointer type */
   HINSTANCE hInst = LoadLibrary("multiply2.dll"); /* load dll and get its handle */
   if (hInst) /* if handle is not null */
   {
      multiply = (MyFunc)GetProcAddress(hInst, "Multiply"); /* get function address */
      if(multiply) /* if pointer is not null, call function via the pointer */
      {
         result = multiply(2, 3); 
         printf("%d x %d = %d", 2, 3, result);
      }
      FreeLibrary(hInst); /* unload dll */
   }
   else
   {
      printf("Unable to load dll");
   }
 
   return 0;
}

Finally, compile this using:

cl test.c

and run the resulting test.exe.

If it works properly, you should see the following output:

2 x 3 = 6







Re: Call C# code in C
Posted By sridevi pc on 30 Nov 2012  
 Hi ,
Thanks for the reply
when i try to do step to am getting errorr message "
multiply.cs(3,21): error CS0106: The modifier 'static' is not valid for this
        item "

csc /t:library multiply.cs

should i make Multiply function as non static 
 

Re: Call C# code in C
Posted By sridevi pc on 30 Nov 2012  
Hi Vulpes, Thanks for the reply when i try to do step to am getting errorr message " multiply.cs(3,21): error CS0106: The modifier 'static' is not valid for this item " csc /t:library multiply.cs should i make Multiply function as non static
Re: Call C# code in C
Posted By sridevi pc on 30 Nov 2012  
Hi Vulpes i have removed non static key word now csc /t:library multiply.cs works fine should i proceed
Re: Call C# code in C
Posted By Vithal Wadje on 30 Nov 2012  
i does not know vulpes sir about it, let us i will learn from you
Vithal Wadje
Re: Call C# code in C
Posted By Vulpes on 30 Nov 2012  
The compiler error suggests that you are using an early version of the C# compiler (v1.0 or v1.1) which doesn't support static classes.

If that's the case, then it's OK to remove 'static' before 'class' but you must leave it in for the Multiply method itself.

Re: Call C# code in C
Posted By sridevi pc on 30 Nov 2012  
i tried all these steps wen i try to run the exe , cmdprompt window pops n vanishes i couldn see the result
Re: Call C# code in C
Posted By Vulpes on 30 Nov 2012  
@ Vithal

No worries, it's not something you'd be likely to know unless (like me) you've spent years inter-operating with unmanaged code.

@ sridevi pc

If the console is closing before you've time to read the output, I'd try inserting the highlighted lines towards the end of the main() function in test.c:

   printf("\n");
   system("pause");
   return 0;

It's also struck me that if you're using a version of the C# compiler prior to 2.0 then you'll also be using a version of ilasm.exe prior to 2.0.

If that's the case then you'll need to do more to the IL than just adding an .export directive (ilasm 2.0 does most of this for you). I've highlighted all the lines that need inserting:


//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.1
//  Copyright (c) Microsoft Corporation.  All rights reserved.



// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly multiply
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module multiply.dll
// MVID: {2E01BB12-10AB-4E3A-9E16-6921ADAAAA0D}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000002    // 32BITREQUIRED - change current .corflags setting from 1 
.vtfixup[1] int32 fromunmanaged at VT_01
.data VT_01 = int32(0)

// Image base: 0x003D0000


// =============== CLASS MEMBERS DECLARATION ===================

.class public abstract auto ansi sealed beforefieldinit Arithmetic
       extends [mscorlib]System.Object
{
  .method public hidebysig static int32  Multiply(int32 num1,
                                                  int32 num2) cil managed
  {
    .vtentry 1:1
    .export [1] as Multiply  
    // Code size       9 (0x9)
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  ldarg.1
    IL_0003:  mul
    IL_0004:  stloc.0
    IL_0005:  br.s       IL_0007

    IL_0007:  ldloc.0
    IL_0008:  ret
  } // end of method Arithmetic::Multiply

} // end of class Arithmetic


// =============================================================

// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file multiply2.res




 

Re: Call C# code in C
Posted By Vulpes on 10 Jan 2013  
You should have started a new thread for this question as it doesn't appear to have anything to do with the subject of this thread and the code is virtually unreadable in any case.

The only obvious problem I can see is that 'List' is used without a type parameter if this is the same List as the framework class, System.Collections.Generic.List<T>.

I'd have thought it needed to be List<double>.

SPONSORED BY

Custom Software Development
MCN is your source for developing solutions involving websites, mobile apps, cloud-computing, databases, BI, back-end services and processes and client-server applications.