是否有可能从C#.Net调用C函数

我有一个C库,并希望从C#应用程序的这个库中调用函数。 我试图通过添加C库文件作为链接器input并添加源文件作为额外的依赖关系来在C库上创build一个C ++ / CLI包装器。

有没有更好的方法来实现这一点,因为我不知道如何将C输出添加到C#应用程序。

我的C代码 –

__declspec(dllexport) unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen); 

我的CPP包装 –

 long MyClass::ConnectSessionWrapper(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen) { return ConnectSession(handle, publicKey, publicKeyLen); } 

这个例子将是,对于Linux

1)用这个内容创build一个C文件libtest.c

 #include <stdio.h> void print(const char *message) { printf("%s\\n", message); } 

这是一个简单的printf封装。 但是代表你想调用的库中的任何C函数。 如果你有一个C++函数,不要忘了把外部C以避免改名。

2)创buildC#文件

 using System; using System.Runtime.InteropServices; public class Tester { [DllImport("libtest.so", EntryPoint="print")] static extern void print(string message); public static void Main(string[] args) { print("Hello World C# => C++"); } } 

3)除非你的库libtest.so在像“/ usr / lib”这样的标准库path中,否则很可能会看到一个System.DllNotFoundException,要解决这个问题,可以将libtest.so移动到/ usr / lib,或者更好的是,只需将您的CWD添加到库path: export LD_LIBRARY_PATH=pwd

学分来自这里

编辑

对于Windows而言 ,并没有太大的不同。 从这里举一个例子,你只有在你的*.cpp文件中用extern "C"括起你的方法

 extern "C" { //Note: must use __declspec(dllexport) to make (export) methods as 'public' __declspec(dllexport) void DoSomethingInC(unsigned short int ExampleParam, unsigned char AnotherExampleParam) { printf("You called method DoSomethingInC(), You passed in %d and %c\n\r", ExampleParam, AnotherExampleParam); } }//End 'extern "C"' to prevent name mangling 

然后编译,并在你的C#文件中做

 [DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")] public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam); 

然后使用它:

 using System; using System.Runtime.InteropServices; public class Tester { [DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")] public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam); public static void Main(string[] args) { ushort var1 = 2; char var2 = ''; DoSomethingInC(var1, var2); } } 

您可以使用P / Invoke从C#直接调用C函数。
下面是一个关于创build一个C#文件的简单方法。

  1. 创build一个新的C#库项目(我将称之为“包装”)
  2. 将一个Win32项目添加到解决scheme,将应用程序types设置为:DLL(我将称之为“CLibrary”)

    • 你可以删除所有其他的cpp / h文件,因为我们不需要它们
    • 将CLibrary.cpp文件重命名为CLibrary.c
    • 添加一个CLibrary.h头文件
  3. 现在我们需要configurationCLibrary项目,右键单击它并转到属性,然后selectConfiguration:“All Configurations”

    • 在configuration属性> C / C ++>预编译头文件中,将预编译头文件设置为:“不使用预编译头文件”
    • 在同一个C / C ++分支中,转到高级,将编译方式更改为:“编译为C代码(/ TC)”
    • 现在在链接器分支中,转到常规,并将输出文件更改为:“$(SolutionDir)Wrapper \ $(ProjectName).dll”,这将复制内置的C DLL到C#项目根目录。

CLibrary.h

 __declspec(dllexport) unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen); 

CLibrary.c

 #include "CLibrary.h" unsigned unsigned long ConnectSession(unsigned long handle, unsigned char * publicKey, unsigned char publicKeyLen) { return 42; } 
  • 右键单击CLibrary项目,生成它,所以我们得到C#项目目录中的DLL
  • 右键单击C#Wrapper项目,添加现有项目,添加CLibrary.dll
  • 单击CLibrary.dll,转到属性窗格,将“复制到输出目录”设置为“始终复制”

将Wrapper项目依赖于CLibrary是一个好主意,所以CLibrary首先被构build,可以通过右键单击Wrapper项目,进入“Project Dependencies”并选中“CLibrary”来实现。 现在对于实际的包装代码:

ConnectSessionWrapper.cs

 using System; using System.Runtime.InteropServices; namespace Wrapper { public class ConnectSessionWrapper { [DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)] unsafe static extern UInt32 ConnectSession(UInt32 handle, char* publicKey, char publicKeyLen); public unsafe UInt32 GetConnectSession(UInt32 handle, string publicKey, char publicKeyLen) { //"Convert" string to char* char* pubKey; fixed (char* bptr = publicKey) { pubKey = (char*)bptr; } return ConnectSession(handle, pubKey, publicKeyLen); } } } 
  • 最后要做的就是右键单击Wrapper项目,将Configuration设置为“All Configurations”,然后选中Allow unsafe code
    使用不安全的代码的唯一原因是因为你有一个char *作为参数,我们需要将一个string转换为固定的字符指针。

结果:
在控制台应用程序中测试包装库

好吧,打开VS 2010,转到文件 – >新build – >项目 – > Visual C ++ – > Win32 – > Win32项目,并给它一个名称(HelloWorldDll在我的情况),然后在窗口下面的应用程序typesselect'DLL '并在Additonal Options下select'Empty Project'

现在转到你的解决scheme资源pipe理器选项卡,通常在VS窗口的右侧,右键单击源文件 – >添加项目 – > C ++文件(.cpp),并给它一个名字(HelloWorld在我的情况)

然后在新的类中粘贴这段代码:

 #include <stdio.h> extern "C" { __declspec(dllexport) void DisplayHelloFromDLL() { printf ("Hello from DLL !\n"); } } 

现在build立项目,导航到您的项目DEBUG文件夹,那里你应该find: HelloWorldDll.dll

现在,让我们创build我们的C#应用​​程序,它将访问DLL,转到文件 – >新build – >项目 – > Visual C# – >控制台应用程序,并给它一个名称(CallDllCSharp),现在复制并粘贴到您的主代码:

 using System; using System.Runtime.InteropServices; ... static void Main(string[] args) { Console.WriteLine("This is C# program"); DisplayHelloFromDLL(); Console.ReadKey(); } 

并build立程序,现在我们已经build立了我们的应用程序可以使用它们,让你的* .dll和你的.exe(bin / debug / .exe)在同一个目录中,并执行应用程序输出应该是

这是C#程序

你好,DLL!

希望能清除你的一些问题。

参考文献

  • 如何在C中创buildDLL库,然后在C#中使用它