通过C接口传递C ++ I / O类的编译器特定问题

时间:2017-08-22 12:36:10

标签: c++ boost-asio

我有一个似乎是由我的编译器引起的问题。当我使用Mingw编译DLL时,一切似乎都正常。当我用MSVC编译DLL时,代码似乎阻塞在createMdl中的某个地方。该过程保持0%的CPU使用率,我从不从下面的函数createMdl函数调用返回。

此代码在一个大型远程环境中运行,因此要在我的机器上进行调试,我创建了一个描述下面问题的框架。不幸的是,这段代码并没有表现出我所看到的行为,但确实描述了我试图做的事情。

申请:

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <windows.h>

int main()
{
  boost::asio::io_service io;
  boost::asio::io_service::work work(io);
  boost::thread t(boost::bind(&boost::asio::io_service::run, &io));

  HMODULE h = LoadLibrary("MyLib.dll");

  typedef void (*createMdl_fn)(void*);
  createMdl_fn createMdl = (createMdl_fn)GetProcAddress(h, "createMdl");

  createMdl((void*)&io);
}

DLL:

#include <boost/asio.hpp>

extern "C" __declspec(dllexport) void __cdecl createMdl(void* io)
{
    boost::asio::io_service*       io_svc = (boost::asio::io_service*)io;
    boost::asio::ip::udp::endpoint endpoint(boost::asio::ip::udp::v4(), 12345);
    boost::asio::ip::udp::socket   sock(*io_svc, endpoint);

    char* buf = new char[256];
    sock.async_receive_from( boost::asio::buffer(buf, 256),
                              endpoint,
                              [buf](const boost::system::error_code& e,
                                  std::size_t b){});
}

你能看到这种方法的缺陷吗?这种方法有什么不稳定的吗?如果您认为(void*)的{​​{1}}投射是个问题,那么在使用io_service时如何进行?请注意,无论使用哪种编译器编译应用程序,我都会遇到相同的行为。

我可以看到的一个大问题是,如果我使用新版本的boost重新编译库,GetProcAddress的定义可能会发生变化,这可能会导致问题,但这并不能解释问题我和#39;我现在有。

1 个答案:

答案 0 :(得分:1)

如果你在不同的编译单元/ DLL /可执行文件/之间传递C ++对象,你必须使用相同的编译器构建它们,否则绝对保证一切都会爆炸并爆炸。

不同的C ++编译器具有非常不兼容的ABI。这与C编译器形成鲜明对比,通常在任何给定平台上具有兼容的ABI,并且可以安全地混合和匹配。

无需将指针转换为void *或将函数声明为extern&#34; C&#34;在这种情况下。 (除了使用GetProcAddress的函数外)。

只有在您将它们之间共享的数据限制为内置类型和C兼容结构时,才能使用不同的C ++编译器。永远不要使用虚函数或访问说明符,指向成员或标准库类型的类 - 简而言之,没有什么能使C ++与C不同。如果使用不同的C ++编译器,则必须声明函数和对象在整个边界为extern "C"

使用来自一个供应商的C ++编译器和来自不同供应商的C编译器通常不是问题。