我正在为一个游戏编写一个bot,它有一个C++ API接口(即,当事件发生时,游戏调用Cpp dll中的方法,dll可以回调游戏中的方法以触发动作)。我并不想用C编写我的机器人程序,我是一个相当有经验的C#程序员,但我完全没有C的经验。所以,显而易见的解决方案是使用ipc将事件发送到C#程序,并将操作发送回C程序,这样我只需要用C编写一个调用方法和发送事件的基本框架。什么是最好的方法来做到这一点?样本代码将非常感谢,因为我没有特别的愿望学习C++在这一点上!
0aydgbwb1#
有lots of different ways of doing IPC in Windows。对于C#到C++,我很想在C++(WinSock是可以的,一旦你了解它)和C#下使用套接字作为API,这是相当容易的。Named Pipes可能更好,如果你不想使用套接字,并且是专门为IPC设计的。C++下的API看起来很简单,例如here。
4xrmg8kj2#
一种解决方案是使用常规__declspec(dllexport)函数创建托管C类库,这些函数调用引用的C#类库中的托管方法。示例-托管C项目中的C++代码文件:
__declspec(dllexport)
#include "stdafx.h" __declspec(dllexport) int Foo(int bar) { csharpmodule::CSharpModule mod; return mod.Foo(bar); }
C#模块(方案中的个别项目):
namespace csharpmodule { public class CSharpModule { public int Foo(int bar) { MessageBox.Show("Foo(" + bar + ")"); return bar; } } }
请注意,我是通过使用System.Windows.Forms.MessageBox.Show调用来演示这是一个实际的.NET调用。基本(非CLR)Win32主控台应用程序范例:
System.Windows.Forms.MessageBox.Show
__declspec(dllimport) int Foo(int bar); int _tmain(int argc, _TCHAR* argv[]) { std::cout << Foo(5) << std::endl; return 0; }
请记得将Win32主控台应用程序与Managed C++项目建置所产生的.lib档案链接。
.lib
wecizke33#
在这种情况下,我希望看到一个C++/CLI方和一个C#方使用.NET框架的命名管道。
v7pvogib4#
我已经写了一个使用管道的阻塞版本。但是游戏调用的方法都不允许阻塞这个问题是通过在一个单独的线程中运行阻塞管道函数来解决的。我发现这个问题正在寻找一个更好的解决方案,但这里是我目前所拥有的基本想法:
#include <mutex> // #include ... HANDLE pipe; char* pipeBuffer; int pipeSize; bool pipeHasData = false; std::mutex m; std::condition_variable cv; void named_pipe() { // optional int pid = _getpid(); std::wstring pipe_name = L"\\\\.\\pipe\\Game-" + std::to_wstring(pid); // (very) shortened loop to show mutex lock // add your own error checking and retrying hPipe = init_named_pipe(pipe_name); while (true) { if (PeekNamedPipe(hPipe, NULL, 0, NULL, &bytesAvailable, NULL) == FALSE) { break; } pipeBuffer = buffer; pipeSize = dwRead; pipeHasData = true; { std::unique_lock<std::mutex> lock(m); cv.wait(lock); } } } void (__fastcall* oGame_Tick)(float deltaTime); void __fastcall hkGame_Tick(float deltaTime) { oGame_Tick(deltaTime); if (pipeHasData) { // parse the packet received in pipeBuffer and call your game actions // respond by writing back to pipe ProcessPipe(pipe, pipeBuffer, pipeSize); { m.lock(); pipeHasData = false; pipeBuffer = nullptr; pipeSize = NULL; m.unlock(); cv.notify_all(); } } } // called once on dll attach void __cdecl init() { // hook gameloop tick function here // start loop in new thread std::thread t1(named_pipe); t1.detach(); }
注意事项:
4条答案
按热度按时间0aydgbwb1#
有lots of different ways of doing IPC in Windows。对于C#到C++,我很想在C++(WinSock是可以的,一旦你了解它)和C#下使用套接字作为API,这是相当容易的。
Named Pipes可能更好,如果你不想使用套接字,并且是专门为IPC设计的。C++下的API看起来很简单,例如here。
4xrmg8kj2#
一种解决方案是使用常规
__declspec(dllexport)
函数创建托管C类库,这些函数调用引用的C#类库中的托管方法。示例-托管C项目中的C++代码文件:
C#模块(方案中的个别项目):
请注意,我是通过使用
System.Windows.Forms.MessageBox.Show
调用来演示这是一个实际的.NET调用。基本(非CLR)Win32主控台应用程序范例:
请记得将Win32主控台应用程序与Managed C++项目建置所产生的
.lib
档案链接。wecizke33#
在这种情况下,我希望看到一个C++/CLI方和一个C#方使用.NET框架的命名管道。
v7pvogib4#
我已经写了一个使用管道的阻塞版本。但是游戏调用的方法都不允许阻塞
这个问题是通过在一个单独的线程中运行阻塞管道函数来解决的。我发现这个问题正在寻找一个更好的解决方案,但这里是我目前所拥有的基本想法:
注意事项: