2011-08-21 62 views
1

我正在尝试为诸如win32,mac os,linux,iOs等平台创建一个抽象层。我想要这个动态链接。在不支持的平台上,它不应该成为一个问题,因为从我看到的所有可以编译为动态库的内容都可以编译为静态库,并且对代码的影响最小。关于C++命名约定的问题

现在去的这点:

我创建了一个名为IThread接口和一个名为CThread类。我使用了一个名为CreateThread的函数,该函数使用extern“C”定义,以便能够将其导出并在库外调用它。这里的问题是,在win32中,例如已经有一个名为CreateThread的函数,因此我得到一个链接器错误。我了解错误以及它出现的原因,但我不确定避免这种情况的好方法。我并不喜欢使用奇怪的命名,像CreateQtThread一样使用qt。
我的另一个想法是创建一个创建CThread实例的线程管理器/工厂,但我不确定这将是一个好主意。

你们对此有何看法?我在问,因为我不想冲这样的重要组织问题。

非常感谢您

+2

你的问题是什么?你明白错误,你不想重命名你的函数,所以你想知道我们对此有何看法? –

+0

是的,如果可能的话,我希望有更多经验的人员就此发表意见。谢谢。 – Sanctus2099

+0

是否希望您的抽象层仅用于C++或其他语言(如C)?你是否想从给定的C++编译器使用它(并且如果你需要改变编译器,则重新编译你的抽象层)或者oyu是否需要“一旦编译一次就可以编译C++”? – ysdx

回答

5

我用一个与外部的“C”定义为能够出口,并把它称为库之外的功能命名的CreateThread。

这很糟糕。我无法谈论其他平台,但在Windows上,导出C++函数是完全正确的。他们只是被打乱了,你会得到一些理智的检查,以防有人改变声明。实际上,这是导出一个函数的唯一正确方法,即 C++。如果你将它声明为extern“C”,那么你不会得到命名空间,也不会超载,如果异常从你的函数中退出,那么编译/EHsc的人将会遇到麻烦。

首选解决方案:不要将它们声明为extern“C”,并将它们放在名称空间中。

唯一的其他解决办法:好,你猜为什么所有的C库前缀它们的职能处理their_lib_prefix_function ...

+0

为什么我使用extern“C”有一个很好的理由。如果我用Visual Studio 2010编译DLL,那么我可以在Visual Studio 2008中使用DLL,而无需重新编译整个事情。实际上,我可以给某人DLL和必要的包含文件(接口),并且该人员可以在没有实际源文件的情况下使用dll编译项目(因为函数的名称没有被损坏)。 – Sanctus2099

+0

@Sanctus:我认为你的理解是错误的。 AFAIK在过去的10年里,这个加工方案并没有改变。 – ybungalobill

+0

我不确定它是否在不同版本的visual studio之间有所不同,但在不同的编译器如gcc上有所不同。这里有一个表格显示了这个:http://en.wikipedia.org/wiki/Name_mangling – Sanctus2099

5

你使用的extern“C”的决定是合理的,我认为,因为它允许从其他语言访问,编译器等。但是这样做意味着你不能使用命名空间,所以你只需要在你的函数前添加一些东西来标识它们来自你的库,一个穷人的命名空间,如果你愿意的话。

这是如果你想使用extern“C”必须做出的折衷。

5

嗯,我不知道你是否会喜欢这个,因为我知道我与之合作的C开发人员发现它不美观。但是,它非常简单并且可以防止这样的碰撞。 (或多或少地在this answer中用“their_lib_prefix_function”注释提到)。

因此,无论何时我使用C代码,我都会使用下划线来基本'命名空间'我的函数。所以,假设你的名字空间是MegaAbstraction,那么类似CreateThread就变成了MegaAbstraction_CreateThread。十分简单。除非别人有名为MegaAbstraction的命名空间,在这种情况下,我建议找到一个不太可能被其他人使用的命名空间。;)

+0

我的+1,我认为那简单而优雅。我并没有发现有点迂腐,坚持要有相同的函数名称,如下所示:1.只要函数名称有意义,就没有关系。 2.在一个实际的项目中,有100多个&1000的事情在为命名具有特定名称的函数而烦恼。 –

+0

:)谢谢,两点都完全同意你的看法。而且,你知道可怕的是,我认为我与之合作的那些人不喜欢我的命名规则,他们担心......他们需要输入多少额外的信件。 :DI的意思是,我以前在使用这些超长的描述性名称时甚至是时髦的,尽管我已经削减了一点自己,我的意思是......如果你正在查看他们的代码,那么它应该是显而易见的给你什么kfifl()的意思,如果你不能区分kfifs()和kfifc()和kfifj()的含义,那么这就是你的问题,而不是他们的问题。耸肩。 – shelleybutterfly

+0

我会留下我讨厌与这样的人一起工作。我相信一个很好的来源就是那个简单明了,能够被下一个在其中工作的人理解的来源。编写令人讨厌的代码,除了作者所理解的没有人是真正的维护噩梦。哎呀! –

1

您的CreateThread使用stdcall调用约定(又名WINAPI)吗?如果使用cdecl调用约定,则应该将函数名称导出为_CreateThread,并避免与Win32 CreateThread函数的链接冲突。

extern "C" _declspec(export) int _cdecl CreateThread(... 
0

在Qt中没有“CreateQtThread”函数,甚至没有类似的东西。有一个QThread类,它有构造函数。如果需要,您可以将所有内容放入命名空间中。