是否有更简单的实例化静态库的方法?

时间:2014-09-05 09:49:03

标签: c++ c

我有这个静态C库,我需要运行多线程(线程彼此没有交互,我只需要同时多个它们来更快地完成工作)。我还将c库包装到c ++ cli库中,然后由c#main应用程序使用。

由于静态库对通过它运行的多个线程没有很好的响应(这是我无法控制的,我没有其依赖的来源),我已经采取了复制(轻微变量)整个事情多次,并在c ++ cli库(及其副本)和c#应用程序之间放置另一个包装器,模拟副本最多8个对象实例。它有效,但对库的功能进行任何更改都相当粗糙和繁琐。

有人知道一种更简单的方法来达到同样的效果吗?最好的猜测我有一些静态内存是在同一个库中工作的多个线程之间发生冲突的地方,有没有办法强制所有静态变量都是特定于线程的? (无法向他们添加declspec线程)。

2 个答案:

答案 0 :(得分:1)

由于您通过C ++ / CLI层使用C#中的C库,听起来您的链接关系如下所示:

(C#application) - dynamic - >(C ++ / CLI DLL) - static - >(C library)

<强>背景

因为您声明无法修改或以其他方式修复C库,所以在没有以某种方式复制内存中的C库的情况下,您实际上无法解决线程安全问题,这将有效地复制全局数据。 /肯定会导致线程冲突。

无论你如何看待它,通过DLL复制(你当前的方法)解决这个问题的唯一方法就是要求你提前知道你需要多少重复项,并且每个DLL都需要稍微不同的导出符号名称(例如,每个都需要C ++ / CLI托管对象类的不同类或命名空间名称)。正如你所说,这确实是粗糙的(我将难以管理,无法扩展)。

<强>解决方案:

我认为你更好更清洁的选择是通过EXE重复。为此,您将在C ++ / CLI DLL前面插入一个新的EXE,并通过您选择的IPC机制(IPC Mechanisms in C# - Usage and Best Practices)动态链接到它。让我们称之为EXE您的服务EXE。如果为主C#应用程序中的每个线程实例化一个服务EXE,那么每个服务EXE将加载它自己的C ++ / CLI DLL副本,从而加载它自己的C库版本。这意味着每个线程都通过服务EXE在C库的副本上运行。

以下是您的链接关系:

(C# application)--IPC-->(C# service EXE)--dynamic-->(C++/CLI DLL)--static-->(C library)

在物理文件术语中,它看起来像这样:

MainApp.exe--IPC-->ServiceApp.exe--dynamic-->CppCliWrapper.dll

要优化此解决方案,您应该尝试避免繁重的线程创建/删除,因为这涉及创建/删除服务EXE。例如,您可以在启动时预先分配X个线程,并在整个应用程序生命周期中使用这些线程。您还可以考虑对操作进行批处理以优化IPC开销。所有这些都取决于您的应用程序的需求和细节。

为了更进一步,如果您选择通过TCP / IP工作的IPC机制,您可以跨机器扩展此解决方案。然后,您可以根据需要在多台计算机上进行操作。这就是许多公司将DLL转变为水平可扩展服务的方式。它并不像听起来那么容易,但是如果你需要扩展这个东西,那就是食物。

答案 1 :(得分:0)

问题似乎是图书馆不是可重入的。如果您可以访问库源代码,最好的办法是搜索所有全局变量并使它们成为本地线程。这可以使用C ++ 11上的thread_local关键字或使用__thread关键字进行,如果使用gcc / g ++进行编译。

这确保了每个线程上将使用每个全局变量的不同副本。