读书人

linux上编写动态库函数为什么要加 ext

发布时间: 2013-02-05 10:40:57 作者: rapoo

linux下编写动态库函数为什么要加 extern "C"
本人想在一个动态库中写两个同名的函数(重载), 发现不行, 因为extern "C", 就相当于以C的接口方式导出, 而C是不支持函数重载的; 然后我去掉"C"(之后连extern也去掉了来试), 可以编译, 但linux下别的程序调用这个动态库的函数时, 报: "找不到函数定义"
查看了一些第三方库的函数定义方式: 都有加extern "C"(C++程序调用它时), 暂且理解为: 他们打算把所有的函数都以C的接口方式导出

那么, 我想问两个问题:
1. linux下编写动态库函数为什么要加 extern "C"
2. 我想导出重名函数怎么做?

(windows下倒是怎么做都可以)

[解决办法]

引用:
linux下没有现成的COM吗?
没有的话就自己实现个类似COM的接口。
然后你所有需要实现的函数,通过这个统一的接口导出即可。

嗯,要是不懂COM的话。
那最简单的方法就是调用方申请数个函数指针。
然后通过一个动态库的统一接口传入(记得接口参数需要申请2级指针)。
动态库接口实现中再分别对这些指针,分别赋值上使用需要的函数地址。

[解决办法]
不同的C++编译器name mangeling的方法不同。
[解决办法]
仅供参考:
UnDecorateSymbolName
The UnDecorateSymbolName function undecorates decorated C++ symbol names.

DWORD UnDecorateSymbolName(
IN LPSTR DecoratedName,
OUT LPSTR UnDecoratedName,
IN DWORD UndecoratedLength,
IN DWORD Flags
);

Parameters
DecoratedName
Pointer to a null-terminated string that specifies a decorated C++ symbol name. This name can be identified by the first character of the name, which is always a question mark (?).
UnDecoratedName
Pointer to a null-terminated string that specifies the buffer that receives the undecorated name.
UndecoratedLength
Specifies the length of the UnDecoratedName buffer.
Flags
Specifies how the decorated name is undecorated. This parameter can be zero or any combination of the following values: Value Description
UNDNAME_COMPLETE Enable full undecoration.
UNDNAME_NO_LEADING_UNDERSCORES Remove leading underscores from Microsoft keywords.
UNDNAME_NO_MS_KEYWORDS Disable expansion of Microsoft keywords.
UNDNAME_NO_FUNCTION_RETURNS Disable expansion of return types for primary declarations.
UNDNAME_NO_ALLOCATION_MODEL Disable expansion of the declaration model.
UNDNAME_NO_ALLOCATION_LANGUAGE Disable expansion of the declaration language specifier.
UNDNAME_NO_MS_THISTYPE Disable expansion of Microsoft keywords on the this type for primary declaration.


UNDNAME_NO_CV_THISTYPE Disable expansion of CodeView modifiers on the this type for primary declaration.
UNDNAME_NO_THISTYPE Disable all modifiers on the this type.
UNDNAME_NO_ACCESS_SPECIFIERS Disable expansion of access specifiers for members.
UNDNAME_NO_THROW_SIGNATURES Disable expansion of throw-signatures for functions and pointers to functions.
UNDNAME_NO_MEMBER_TYPE Disable expansion of the static or virtual attribute of members.
UNDNAME_NO_RETURN_UDT_MODEL Disable expansion of Microsoft model for UDT returns.
UNDNAME_32_BIT_DECODE Undecorate 32-bit decorated names.
UNDNAME_NAME_ONLY Crack only the name for primary declaration. Returns [scope::]name. Does expand template parameters.
UNDNAME_NO_ARGUMENTS Do not undecorate function arguments.
UNDNAME_NO_SPECIAL_SYMS Do not undecorate special names, such as vtable, vcall, vector, metatype, and so on.


Return Values
If the function succeeds, the return value is the number of characters in the UnDecoratedName buffer, not including the NULL terminator.

If the function fails, the return value is zero. To retrieve extended error information, call GetLastError.

Remarks
If the function fails and returns zero, the content of the UnDecoratedName buffer is undetermined.

QuickInfo
Windows NT: Requires version 4.0 or later.
Windows: Requires Windows 95 or later. Available as a redistributable for Windows 95.
Windows CE: Unsupported.
Header: Declared in imagehlp.h.
Import Library: Use imagehlp.lib.

See Also
PE Image Helper (ImageHlp) Overview, ImageHlp Debugger Functions



[解决办法]
由于c++中有函数重载,c中没有这个概念。
如果C++程序要调用已经被编译后的C 函数,该怎么办?
假设某个C 函数的声明如下:
void foo(int x, int y);
该函数被C 编译器编译后在库中的名字为_foo,而C++编译器则会产生像_foo_int_int
之类的名字用来支持函数重载和类型安全连接。由于编译后的名字不同, C++程序不能
直接调用C 函数。C++提供了一个C 连接交换指定符号extern“C”来解决这个问题。
例如:
extern “C”
{
void foo(int x, int y);
… // 其它函数
}
或者写成
extern “C”
{
#include “myheader.h”
… // 其它C 头文件
}
这就告诉C++编译译器,函数foo 是个C 连接,应该到库中找名字_foo 而不是找
_foo_int_int。C++编译器开发商已经对C 标准库的头文件作了extern“C”处理,所以我
们可以用#include 直接引用这些头文件。
[解决办法]
c++中引用c语言函数,也要加“extern c”
[解决办法]
extern "C"不能导出重名函数吧
[解决办法]
extern "C" 是c++调用c函数必须的

[解决办法]
10L的可以参考下
------解决方案--------------------


引用:
不同的C++编译器name mangeling的方法不同。
++
[解决办法]
//像这样写,只要使用同一个编译器,动态库中写两个同名的函数(重载)
//应该也没问题
//定义一个接口类
apiInterface.h
class apiInterface{
virtual void Hello()=0;
virtual void Hello(const string &s)=0;
virtual ~apiInterface()=0;
}

动态库,其中中写两个同名的函数(重载)

class apiInterface_Impl{
apiInterface_Impl(){};

void Hello(){
cout<< "hello world!"<<endl;
};
void Hello(const string &s){
cout<< "hello " <<s <<endl;
};

virtual ~apiInterface_Impl(){};
}
//只需要导出两个函数
extern "C" apiInterface* Create_apiInterface(){return new apiInterface_Impl();};
//可以不要
extern "C" apiInterface* Destory_apiInterface(apiInterface*p ){ delete p;};
//主程序:
#include "apiInterface.h"
int main()
{
apiInterface*p= Create_apiInterface();
p->Hello();
string s("zhangwanglizhao")
p->Hello(s);
//不要Destory_apiInterface 的话直接改delete p;
Destory_apiInterface(p);
return 0;
}
试一下如何!

读书人网 >C++

热点推荐