2010-05-26 60 views
2

我在C中创建共享库,但不知道源代码的正确实现是什么。C中的共享库

我想创建例如像一个API,printHello,

int printHello(char * text); 

这printHello功能调用另一个功能:

在源文件中,libprinthello.c,

void printHello(char * text) 
{ 
    printHi(); 
    printf("%s", text); 
} 

由于此printHello功能是用户或应用程序的界面:

在头文件libprinthello.h,

extern void printHello(char * text); 
的printHi功能的源文件中

然后,printhi.c

void printHi() 
{ 
    printf("Hi\n"); 
} 

然后我的问题是,因为printHello是我想的唯一功能在用户中暴露,我应该在printHi函数中做什么实现?

我是否还应该在extern中声明printHi函数?

+0

你应该提到的环境。在我的回应中,我提出了一个既适用于Windows环境又适用于Unix环境的解决方案。 – INS 2010-05-26 08:21:31

回答

1

理想情况下,如果您不希望用户致电printHi()函数,那么它们应该对他们不可见。如果这不可行,则使用约定来指示哪些名称将被用户调用,哪些不是。通常情况下,这是通过领先的下划线完成的,但这可能会导致各种冲突。因此,如果您的库有一个命名约定,那么可以使用pfx_GlobalName()来记录用户可调用的函数,pfxInternalName()可以使用无证函数,反之亦然,或者使用一些相似的约定。然后,您可以简单地告诉用户,不支持直接调用未记录的函数,并且任何对它们的使用在将来的版本中都可能会中断(或者可能会重命名该函数或其他函数)。偶尔做出更改以明确你的意思是说你的意思。

因此,如果隐藏的函数可以放入与已记录的公共函数相同的源模块中,请将它们隐藏起来。如果您不能,请使用命名约定来指示隐藏的功能不适合最终用户使用。

您可以使用GCC控制符号映射和事物符号的可见性;虽然这很烦琐。

+0

你也可以通过使它们成为静态函数来使它不可见,它不像属性那样编译器特定,但是强制代码上的某个结构。 – Hasturkun 2010-05-26 09:15:29

5

您可以使用两个独立的头文件:

libprinthello.h

#ifndef LIBPRINTHELLO_H /* These are include guards */ 
#define LIBPRINTHELLO_H 

void printHello(char * text); 

#endif 

libprinthi.h

#ifndef LIBPRINTHI_H 
#define LIBPRINTHI_H 

void printHi(); 

#endif 

libprinthello.c

#include "libprinthi.h" 
#include "libprinthello.h" 

void printHello(char * text) 
{ 
    printHi(); 
    printf("%s", text); 
} 

libprinthi.c

#include "libprinthi.h" 

void printHi()  
{  
    printf("Hi\n");  
}  

然后用户代码只包含libprinthello.h,并从用户保持libprinthi.h远,使得printHi()看不见他们(用户代码也将连接对共享库):

#include "libprinthello.h" 

int main() 
{ 
    printHello("Hello World!\n"); 
    return 0; 
} 
3

如果你把printHi的定义libprinthello.c, 你可以简单地把它声明静态的,它只会 是在同一 文件中定义的其他功能进行访问。如果您想将自定义翻译单元中的定义放入其 中,则不会有可移植的方式将 隐藏给库的用户,但您可以使用 将它隐藏在实现特定的方式中。例如,对于 示例,使用gcc可以使用 _ _属性_ _((visibility(“hidden”)))。 但是,简单地将声明从 中删除,公共头文件应该足以使 库的用户不使用该函数。

1

考虑这个文件(Export_Macro.h)

#ifndef EXPORT_MACRO_H 
#define EXPORT_MACRO_H 

#ifdef _WINDOWS 
    #ifdef I_WANT_TO_EXPORT_MACROS 
     #define EXPORT_MACRO __declspec(dllexport) 
    #else 
     #define EXPORT_MACRO __declspec(dllimport) 
    #endif 
#else 
    #define EXPORT_MACRO 
#endif 

#endif // EXPORT_MACRO_H 

在源代码中做到这一点:

#include "Export_Macro.h" 
... 
// for functions you want to export outside the DLL (Dynamic Link Library)/so (Shared Object) 
EXPORT_MACRO void printHello(char * text); 

这个工作对我来说相当不错。

更完整的解释和导出宏,你可以找到here

后来编辑:这应该在Unix和Windows中工作,没有任何大问题。

+0

你提供的链接是用于C++的,是C中的行为是否相同? – rzetterberg 2011-10-26 08:45:01

+1

只要你使用'extern“C”'作为从C++导出的函数,但是从C调用的函数就不会有任何问题。如果你只使用C'extern“C”'是可选的。 – INS 2011-10-27 14:09:23

+0

感谢您的回答。 Upvoted – rzetterberg 2011-10-28 07:58:45