创build一个跨进程函数指针

我有两个进程的Windows Mobile 6的Visual Studio 2008 C ++项目。 这两个我想访问process1中包含的相同的function。

该function是Buzz

 struct TEST_STRUCT { int bar; WCHAR foo[ 20 ]; }; typedef int( *pfn_Buzz )( TEST_STRUCT* ); int Buzz( TEST_STRUCT* info ); 

Process1包含Buzz的定义,并在内存映射文件中为其创build函数指针:

 int Buzz( TEST_STRUCT* info ) { info->bar = 1; wsprintf( info->foo, L"Hello!" ); return 100; } int _tmain( int argc, _TCHAR* argv[] ) { // create a memory-mapped file shared memory space that can be read by any process HANDLE mapping = ::CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof( pfn_Buzz ) , NULL ); LPVOID buzz_addr = ::MapViewOfFile( mapping, FILE_MAP_ALL_ACCESS, 0, 0, sizeof( pfn_Buzz ) ); // find our process' memory offset DWORD offset = ::GetCurrentProcessIndex() + 0x02000000; // copy the complete function address to the shared memory space buzz_addr = ( LPVOID )( ( DWORD )&Buzz + offset ); // convert the function address to a string to send to process2.exe WCHAR address[ 9 ] = { 0 }; wsprintf( address, L"%x", ( ( DWORD )buzz_addr ) ); // start process2.exe and wait for it to finish PROCESS_INFORMATION pi = { 0 }; ::CreateProcess( L"\\test_user.exe", address, NULL, NULL, FALSE, 0, NULL, NULL, NULL, &pi ); ::WaitForSingleObject( pi.hProcess, INFINITE ); ::UnmapViewOfFile( buzz_addr ); ::CloseHandle( mapping ); return 0; } 

Process2从Process1接收Buzz的地址,将其转换为pfn_Buzz函数指针并执行。

 // process2.exe int _tmain( int argc, _TCHAR* argv[] ) { // get the address of the Buzz() function pointer WCHAR* wszAddr = argv[ 1 ]; WCHAR* wszAddrEnd = &argv[ 1 ][ 8 ]; DWORD address = wcstol( wszAddr, &wszAddrEnd, 16 ); pfn_Buzz PFNBuzz = ( pfn_Buzz )address; // execute buzz TEST_STRUCT test = { 0 }; PFNBuzz( &test ); return 0; } 

不幸的是,当我尝试执行PFNBuzz函数时,我在PFNBuzz非法指令exception。

任何人都可以build议我可以改变以获得我以后的function?

谢谢,PaulH

如果您希望两个进程使用相同的函数,请将该函数放入一个DLL中,并将该DLL链接到两个进程。 每个进程都有自己的地址空间,所以在一个进程中的地址可能在另一个进程中根本不起作用,即使它“工作”也会指向完全不同的东西。

虽然您正在将偏移量传递给父级的内存映射区域,但是当您尝试在客户端访问它时,我没有看到任何匹配的代码来映​​射相同的区域,并将其基数添加到指针。

Visual C ++有一个__based指针类型,可以简化这一点。

你的问题是由于进程A(启动进程B)有两个完全不同的虚拟地址空间。 你可以传递一个函数指针给进程A,但由于它们的地址空间不同,所以你传递的指针将会减少到另一个进程。 这是过程的巨大奖金之一。

如果您希望在进程间进行通信,那么您将需要使用某种形式的进程间通信(IPC) 。

在windows下做IPC有几种方法。 在我看来,最通用的方法是使用套接字。 套接字给你的好处是你可以分开运行进程A和进程B的机器,并仍然得到你想要的功能。 同样,没有什么能阻止在同一台机器上运行的两个进程。 它提供的灵活性是非常有用的。

所以假设你选择一个基于套接字的IPC方法,那么你实际上做的是远程过程调用(RPC) 。

正如你可能想象的那样,有许多不同的RPC方法。 您可以使用DCOM或Corba 。 Raknet是支持RPC的第三方库。 还有很多其他的解决方案。 我强烈建议对这个问题进行大量的研究。 我提供给你的链接和关键字应该给你一个好的起点:)

您可以简单地使用__declspec(dllexport)导出函数,然后使用GetProcAddress()使用它的名称来加载它。 如果在C ++中,只要记住extern "C"声明禁用名称修改。 考虑:

 extern "C" int __declspec(dllexport) Buzz( TEST_STRUCT* info ) { ... } int main ( int, char ** ) { pfn_Buzz buzz = GetProcAddress(GetmoduleeHandle(NULL), "Buzz"); // ... } 

然后,使用您选择的IPC方法传递函数名称。