2009-06-27 84 views
6

什么是设计的DLL一个C API与传递“对象”,这是C运行时依赖的问题,涉及的最佳方式(FILE * malloc返回指针,等...) 。例如,如果两个DLL与不同版本的运行时间链接,我的理解是,您不能安全地将FILE *从一个DLL传递到另一个DLL。C运行时的对象,DLL边界

是唯一的解决方案使用Windows相关的API(这是保证在DLL工作)? C API已经存在并且已经很成熟,但是主要是从unix设计的(当然,仍然需要在unix上工作)。

回答

0

问题与不同的运行时间,因为FILE *结构属于 一个运行在Windows系统上是不可解。

但是,如果你写一个小包装界面你做了,它并没有真正伤害。

stdcall IFile* IFileFactory(const char* filename, const char* mode); 

class IFile { 

    virtual fwrite(...) = 0; 
    virtual fread(...) = 0; 

    virtual delete() = 0; 
} 

这是保存在各地的dll边界通过,并没有真正伤害。

P.S .:小心如果你开始在dll边界上抛出异常。如果你在Windows操作系统上实现了一些设计方法,但是在其他方面会失败,这将很安静。

1

无论是现有的答案是正确的:由于在Windows下:你有两个DLL,每一个静态两种不同版本的C/C++标准库的链接。

在这种情况下,不应该将指针传递到由C/C++标准库在一个DLL创建到其他结构。原因在于这两个C/C++标准库实现之间的结构可能不同。

你不应该做的另一件事是免费从在其他分配的一个DLL通过新的或的malloc分配的指针。堆管理器也可以不同地实施。

请注意,您可以使用DLL之间的指针 - 它们只是指向内存。这是免费的问题。

现在,你可能会发现这个工作,但如果是这样,那么你只是运气。这可能会在未来导致您的问题。您的问题

一个潜在的解决方案是动态链接到CRT。例如,您可以动态链接到MSVCRT.DLL。这样你的DLL将总是使用相同的CRT。

请注意,我不建议在DLL之间传递CRT数据结构。你可能想看看你是否可以更好地考虑事情。

请注意,我不是Linux/Unix专家 - 但您在这些操作系统上也会遇到同样的问题。

+0

我明白这个问题 - 我要求的是这个问题的答案:)我希望有一个解决方案,它不会假设改变现有的C API(在签名中有FILE *等),但似乎没有如果我不能保证所有的东西都能够链接到相同的C运行时? 尽管在Unix上这个问题在理论上是相同的,但它很少是一个问题,因为只有一个C运行时。我从来没有在文件库之间传递FILE *,unix文件描述符的问题 - 很多C APIS都是这样设计的,并且在这些OS上完美地工作。 – 2009-06-27 16:45:36

0

如果C API存在并且已经成熟,那么使用纯粹的Win32 API API在内部绕过CRT会让你感觉一半。另一半是确保DLL的用户使用相应的Win32 API函数。这会使您的API在使用和文档中的可移植性降低。另外,即使你用这种内存分配方式,CRT函数和Win32函数都处理void *,你仍然遇到文件问题 - Win32 API使用句柄,并且对FILE结构一无所知。

我不太清楚FILE *的局限性,但我认为问题与跨模块的CRT分配相同。 MSVCRT在内部使用Win32来处理文件操作,并且可以从同一进程中的每个模块使用基础文件句柄。可能不起作用的是关闭由另一个模块打开的文件,这涉及在可能不同的CRT上释放FILE结构。

我会做什么,如果更改API仍然是一个选项,导出清除功能的任何可能的“对象”在DLL中创建。这些清理函数将以与在该DLL中创建的方式相对应的方式来处理给定对象的处置。这也将使DLL在使用方面绝对便携。您唯一担心的就是确保DLL的用户确实使用清理函数而不是常规的CRT函数。这可以使用几个技巧,这值得另一个问题...

2

你问一个C,而不是C++解决方案。

在C做这种事情通常的方法(S)是:

  • 设计模块API根本就没有需要CRT对象。获取通过原始C类型传递的东西 - 即让消费者加载文件并简单地向您传递指针。或者,让消费者传递一个完全合格的文件名,在内部打开,阅读和关闭。

  • 其他c模块,MS机柜SD和部分OpenSSL库iirc使用了一种方法,让消费应用程序将指向函数的指针传递给初始化函数。因此,任何传递FILE *的API都会在初始化期间取得一个指向结构的指针,这个结构的函数指针匹配fread,fopen等特征符。当处理外部FILE *时,DLL总是使用传入的功能而不是CRT功能。

通过一些简单的技巧这样你可以让你的C DLL的接口完全独立于主机CRT的 - 或者事实上要求将用C或C++在所有的主机。