我正在为一款游戏编写机器人,该游戏有一个C++ API接口(即当事件发生时,游戏调用Cpp dll中的方法,dll可以回调游戏中的方法来触发动作)。
我不想用C++编写我的机器人,我是一位相当有经验的C#程序员,但我完全没有C++的经验。因此,显而易见的解决方案是使用ipc将事件发送到C#程序,并将动作发送回C++程序,这样我只需要在C++中编写一个基本的框架,以调用方法和发送事件即可。
如何做到最好呢?如果能提供示例代码,那就非常感激了,因为目前我没有学习C++的特别愿望!
我正在为一款游戏编写机器人,该游戏有一个C++ API接口(即当事件发生时,游戏调用Cpp dll中的方法,dll可以回调游戏中的方法来触发动作)。
我不想用C++编写我的机器人,我是一位相当有经验的C#程序员,但我完全没有C++的经验。因此,显而易见的解决方案是使用ipc将事件发送到C#程序,并将动作发送回C++程序,这样我只需要在C++中编写一个基本的框架,以调用方法和发送事件即可。
如何做到最好呢?如果能提供示例代码,那就非常感激了,因为目前我没有学习C++的特别愿望!
一种解决方案是创建一个托管的C++类库,其中包含常规的__declspec(dllexport)
函数,这些函数调用引用的C#类库中的托管方法。
示例 - 托管C++项目中的C++代码文件:
#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调用。__declspec(dllimport) int Foo(int bar);
int _tmain(int argc, _TCHAR* argv[])
{
std::cout << Foo(5) << std::endl;
return 0;
}
.lib
文件链接Win32控制台应用程序。#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();
}
需要注意的事项: