[翻訳]:C/C++コードからC#をどのようにコールバックするか
12717 ワード
声明:ネット上で类似の中国语のブログは大いに存在して、本人の知识のレベルは有限で、アマチュアの趣味、同じくバックアップのために収蔵しますHow to make a callback to C#from C/C++code
知識を共有する初志に基づいて、翻訳してみんなに参考にして、読みやすくて拗ねないように、原文に従って直訳していないで、届かないところあるいは翻訳が間違っているので、まだ噴き出さないでください.
ほとんどの人が非管理DLLの関数を呼び出す方法を知っていますが、C/C++コードからC#コードを呼び出すことを望んでいる場合があります.Engineというシーンを想像してみてください.dllのネイティブC言語DLLのC#アプリケーションを記述します.DLLにDoWorkという名前の関数エントリポイントがあります.呼び出す必要があります.Engine.dllで「DoWork」を呼び出すのは、C#コードで次のように簡単です.
このコードの実行は非常に良好になりますが、DoWorkは継続的に実行されるタスクであり、ユーザー側が更新されることを保証するために、進捗状況を表示したいと考えています.これを実現するには、次のステップが必要です.
1.C#コードに類似の非管理コード委任を定義する
2.Cコードにコールバック署名を定義する
3.CコードでDoWorkの署名を変更してProgressCallbackのアドレスを受信する
注意:DLLマクロの宣言は次のとおりです.
4.C#コードでは、管理されていない委任タイプの委任を作成する必要があります.
5.そして、DoWorkを呼び出すためには、このようにする必要があります.
ここでは、単純なアプリケーションのソースコードの例を示す.このコードセグメントには、ProcessFile関数という名前のCコードがC#にコールバックされ、さらなる処理のためにファイルパスを取得する必要があります.現在の状況では、印刷ファイルの内容をコンソールに印刷します.
Engine.dll/Main.h
Engine.dll/Main.c
TestApp.exe/Program.cs
以下は私がコンパイルしたコードを添付して、原文と少し出入りして、主に私が習慣的に使うためです.NET 2.0は、コンパイル中にコンパイラをスムーズに通過するためのものもあります.
コードはVisual Studio 2010+VC 6を使用する.0作成
ダウンロードアドレス:1.どうやってC_からC++コードでC#をコールバックする.rar
2.どうやってC_からCppコードでCSharpをコールバックする.rar
知識を共有する初志に基づいて、翻訳してみんなに参考にして、読みやすくて拗ねないように、原文に従って直訳していないで、届かないところあるいは翻訳が間違っているので、まだ噴き出さないでください.
ほとんどの人が非管理DLLの関数を呼び出す方法を知っていますが、C/C++コードからC#コードを呼び出すことを望んでいる場合があります.Engineというシーンを想像してみてください.dllのネイティブC言語DLLのC#アプリケーションを記述します.DLLにDoWorkという名前の関数エントリポイントがあります.呼び出す必要があります.Engine.dllで「DoWork」を呼び出すのは、C#コードで次のように簡単です.
[DllImport("Engine.dll")]
public static extern void DoWork();
このコードの実行は非常に良好になりますが、DoWorkは継続的に実行されるタスクであり、ユーザー側が更新されることを保証するために、進捗状況を表示したいと考えています.これを実現するには、次のステップが必要です.
1.C#コードに類似の非管理コード委任を定義する
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void ProgressCallback(int value);
2.Cコードにコールバック署名を定義する
typedef void (__stdcall * ProgressCallback)(int);
3.CコードでDoWorkの署名を変更してProgressCallbackのアドレスを受信する
DLL void DoWork(ProgressCallback progressCallback)
注意:DLLマクロの宣言は次のとおりです.
#define DLL __declspec(dllexport)
4.C#コードでは、管理されていない委任タイプの委任を作成する必要があります.
ProgressCallback callback =
(value) =>
{
Console.WriteLine("Progress = {0}", value);
};
5.そして、DoWorkを呼び出すためには、このようにする必要があります.
DoWork(callback);
ここでは、単純なアプリケーションのソースコードの例を示す.このコードセグメントには、ProcessFile関数という名前のCコードがC#にコールバックされ、さらなる処理のためにファイルパスを取得する必要があります.現在の状況では、印刷ファイルの内容をコンソールに印刷します.
Engine.dll/Main.h
#include "Windows.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define DLL __declspec(dllexport)
typedef void (__stdcall * ProgressCallback)(int);
typedef char* (__stdcall * GetFilePathCallback)(char* filter);
DLL void DoWork(ProgressCallback progressCallback);
DLL void ProcessFile(GetFilePathCallback getPath);
#ifdef __cplusplus
}
#endif
Engine.dll/Main.c
#include "Main.h"
#include
DLL void DoWork(ProgressCallback progressCallback)
{
int counter = 0;
for(; counter<=100; counter++)
{
// do the work...
if (progressCallback)
{
// send progress update
progressCallback(counter);
}
}
}
DLL void ProcessFile(GetFilePathCallback getPath)
{
if (getPath)
{
// get file path...
char* path = getPath("Text Files|*.txt");
// open the file for reading
FILE *file = fopen(path, "r");
// read buffer
char line[1024];
// print file info to the screen
printf("File path: %s
", path ? path : "N/A");
printf("File content:
");
while(fgets(line, 1024, file) != NULL)
{
printf("%s", line);
}
// close the file
fclose(file);
}
}
TestApp.exe/Program.cs
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
class Program
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate void ProgressCallback(int value);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate string GetFilePathCallback(string filter);
[DllImport("Engine.dll")]
public static extern void DoWork([MarshalAs(UnmanagedType.FunctionPtr)] ProgressCallback callbackPointer);
[DllImport("Engine.dll")]
public static extern void ProcessFile([MarshalAs(UnmanagedType.FunctionPtr)] GetFilePathCallback callbackPointer);
[STAThread]
static void Main(string[] args)
{
// define a progress callback delegate
ProgressCallback callback =
(value) =>
{
Console.WriteLine("Progress = {0}", value);
};
Console.WriteLine("Press any key to run DoWork....");
Console.ReadKey(true);
// call DoWork in C code
DoWork(callback);
Console.WriteLine();
Console.WriteLine("Press any key to run ProcessFile....");
Console.ReadKey(true);
// define a get file path callback delegate
GetFilePathCallback getPath =
(filter) =>
{
string path = default(string);
OpenFileDialog ofd =
new OpenFileDialog()
{
Filter = filter
};
if (ofd.ShowDialog() == DialogResult.OK)
{
path = ofd.FileName;
}
return path;
};
// call ProcessFile in C code
ProcessFile(getPath);
}
}
以下は私がコンパイルしたコードを添付して、原文と少し出入りして、主に私が習慣的に使うためです.NET 2.0は、コンパイル中にコンパイラをスムーズに通過するためのものもあります.
コードはVisual Studio 2010+VC 6を使用する.0作成
ダウンロードアドレス:1.どうやってC_からC++コードでC#をコールバックする.rar
2.どうやってC_からCppコードでCSharpをコールバックする.rar