Cライブラリがあり、C#アプリケーションからこのライブラリの関数を呼び出したい。 C libファイルをリンカー入力として追加し、ソースファイルを追加の依存関係として追加することで、C libに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)C
ファイル、libtest.c
を次のコンテンツで作成します。
#include <stdio.h>
void print(const char *message)
{
printf("%s\\n", message);
}
これは、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++");
}
}
3)「/ usr/lib」などの標準ライブラリパスにlibtest.soライブラリがない場合、System.DllNotFoundExceptionが表示される可能性があります。これを修正するには、libtest.soを/ usr/libに移動するか、さらに良いのは、CWDをライブラリパスに追加するだけです:export LD_LIBRARY_PATH=pwd
ここ からのクレジット
[〜#〜] edit [〜#〜]
Windowsの場合、それほど違いはありません。 here の例を使用すると、*.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);
}
}
PDATE-2019年2月22日:この答えはかなりの数の賛成票を得ているので、Cメソッドを呼び出すより良い方法でそれを更新することにしました。以前はunsafe
コードを使用することを提案していましたが、安全で正しい方法は、MarshalAs
属性を使用して.NET string
をchar*
に変換することです。また、VS2017にはWin32プロジェクトはもうありません。おそらく、Visual C++ dllまたは空のプロジェクトを作成して変更する必要があります。ありがとうございました!
P/Invokeを使用して、C#からC関数を直接呼び出すことができます。
C dllをラップするC#ライブラリを作成する方法を簡単に説明します。
ソリューションにWin32プロジェクトを追加し、アプリケーションタイプをDLL(「CLibrary」と呼びます)
ここで、CLibraryプロジェクトを構成し、それを右クリックしてプロパティに移動し、構成を選択する必要があります:「すべての構成」
CLibrary.h
__declspec(dllexport) unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen);
CLibrary.c
#include "CLibrary.h"
unsigned long ConnectSession(unsigned long handle,
unsigned char * publicKey,
unsigned char publicKeyLen)
{
return 42;
}
WrapperプロジェクトをCLibraryに依存させることをお勧めします。CLibraryを最初にビルドするには、Wrapperプロジェクトを右クリックし、[プロジェクトの依存関係]に移動して[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);
}
}
}
GetConnectSession
を呼び出すだけで、42
が返されます。
結果:
さて、VS 2010を開き、Goto File-> New-> Project-> Visual C++-> Win32-> Win32 Projectに名前を付けて(私の場合はHelloWorldDll)、次にウィンドウでアプリケーションの種類を選択'DLL'および追加オプションを選択'Empty Project'を選択します。
ソリューションエクスプローラー通常はVSウィンドウの右側のタブに移動し、右クリックソースファイル->アイテムの追加-> C++ファイル(.cpp)に名前を付けます(私の場合はHelloWorld)
次に、新しいクラスに次のコードを貼り付けます。
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromDLL()
{
printf ("Hello from DLL !\n");
}
}
ここでBuildプロジェクトに移動した後、プロジェクトに移動します[〜#〜] debug [〜#〜]フォルダーとそこにあるはずです:HelloWorldDll.dll。
次に、dllにアクセスするC#アプリを作成します。Gotファイル->新規->プロジェクト-> Visual C#->コンソールアプリケーションに名前(CallDllCSharp)を付け、コピーして貼り付けますあなたのメインへのコード:
using System;
using System.Runtime.InteropServices;
...
static void Main(string[] args)
{
Console.WriteLine("This is C# program");
DisplayHelloFromDLL();
Console.ReadKey();
}
両方のアプリがビルドされたので、それらを使用して、同じディレクトリに* .dllと。exe(bin/debug /。exe)を取得し、アプリケーションを実行します。出力は
これはC#プログラムです
DLL!
それがあなたの問題のいくつかを解決することを願っています。
参照: