我有一个C lib,想从C#应用程序调用这个库中的函数.我尝试通过添加C lib文件作为链接器输入并将源文件添加为附加依赖项来在C lib上创建C++/CLI包装器.
有没有更好的方法来实现这一点,因为我不确定如何将C输出添加到c#应用程序.
我的C代码 -
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
Run Code Online (Sandbox Code Playgroud)
我的CPP包装 -
long MyClass::ConnectSessionWrapper(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}
Run Code Online (Sandbox Code Playgroud)
Gon*_*o.- 81
对于Linux,示例将是:
1)创建一个包含以下内容的C文件libtest.c:
#include <stdio.h>
void print(const char *message)
{
printf("%s\\n", message);
}
Run Code Online (Sandbox Code Playgroud)
这是printf的一个简单的伪包装器.但表示C要调用的库中的任何函数.如果你有一个C++功能,别忘了把extern放在一边,C以避免错误的名字.
2)创建C#文件
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++");
}
}
Run Code Online (Sandbox Code Playgroud)
3)除非您在"/ usr/lib"之类的标准库路径中拥有库libtest.so,否则您可能会看到System.DllNotFoundException,为了解决此问题,您可以将libtest.so移动到/ usr/lib,或者更好的是,只需将CWD添加到库路径: 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
Run Code Online (Sandbox Code Playgroud)
然后,编译,并在你的C#文件中做
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]
public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);
Run Code Online (Sandbox Code Playgroud)
然后使用它:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Sha*_*han 28
更新 - 2019年2月22日:由于这个答案已经得到了不少赞成,我决定用更好的方法来调用C方法来更新它.以前我曾建议使用unsafe代码,但安全和正确的方法是使用MarshalAs属性将.NET string转换为char*.此外,在VS2017中不再有Win32项目,您可能必须创建一个Visual C++ DLL或空项目并进行修改.谢谢!
您可以使用P/Invoke直接从C#调用C函数.
这是创建包含C dll的C#lbrary的简短操作方法.
将Win32项目添加到解决方案中,将应用程序类型设置为:DLL(我将其称为"CLibrary")
现在我们需要配置CLibrary项目,右键单击它并转到属性,然后选择Configuration:"All Configurations"
CLibrary.h
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
Run Code Online (Sandbox Code Playgroud)
CLibrary.c
#include "CLibrary.h"
unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return 42;
}
Run Code Online (Sandbox Code Playgroud)
让Wrapper项目依赖于CLibrary是一个好主意,所以首先构建CLibrary,你可以通过右键单击Wrapper项目,转到"Project Dependencies"并检查"CLibrary"来实现.现在为实际的包装代码:
ConnectSessionWrapper.cs
using System.Runtime.InteropServices;
namespace Wrapper
{
public class ConnectSessionWrapper
{
[DllImport("CLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern uint ConnectSession(uint handle,
[MarshalAs(UnmanagedType.LPStr)] string publicKey,
char publicKeyLen);
public uint GetConnectSession(uint handle,
string publicKey,
char publicKeyLen)
{
return ConnectSession(handle, publicKey, publicKeyLen);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在只需打电话GetConnectSession,它应该返回42.
结果:

| 归档时间: |
|
| 查看次数: |
60430 次 |
| 最近记录: |