我有一个DLL,需要访问存储在主机应用程序中的STL容器中的数据.因为C++没有标准的ABI,并且我想支持不同的编译器,所以应用程序和DLL之间的接口基本上必须保持普通的旧数据.
对于向量,这是相对简单的.你可以简单地返回向量的内存块,因为它保证是有条件的:
// To return vector<int> data
virtual void GetVectorData(const int*& ptr, size_t& count) const
{
if (!vec.empty())
ptr = &(vec.front());
count = vec.size();
}
Run Code Online (Sandbox Code Playgroud)
现在,DLL可以通过该接口对向量的数据进行安全的只读访问.DLL也可以包装它以将内容复制到自身的向量中.
那么STL列表(和deques)呢?是否有另一种直接允许通过DLL边界访问的方法?或者我是否必须使用某种GetFirst()/ GetNext()接口?我可能需要为很多列表执行此操作,因此有一个像vector一样简单的解决方案会很好.
我的Linux系统上的所有标准共享库(Fedora 9)都将ELFOSABI_NONE(0)指定为OSABI.
这很好 - 但是我收到了供应商的共享库,其中ELF头中给出的OSABI是ELFOSABI_LINUX(3).
这对于用于Linux系统的共享库来说听起来不是一个不合理的值,但是它与我所有其他库的值不同 - 所以当我尝试使用dlopen()从一个库中打开这个库时我的其他库失败,错误"ELF文件操作系统ABI无效".
我编译了FreeBSD实用程序brandelf.c并使用它将OSABI类型更改为0,现在库似乎可以正常运行其他所有内容.
我只是想知道 - 为什么你认为这个库被标记为ELFOSABI_LINUX?我猜它们可能在另一个系统上交叉编译并指定了一些gcc标志,导致这个值被设置到ELF标题中?我试图实现类似的东西,但无法确定适当的gcc标志或标志.
我想知道可能的原因是什么,因为这个特定的供应商在没有大量手持的情况下不会做任何事情,我希望能够说"你可能正在做X但是这意味着我们必须修改你的库在我们收到它们之后".
根据维基百科,英特尔ABI允许使用EAX,ECX而EDX不是在功能中保留它们.
我不确定"Intel ABI"是什么意思.这是否意味着所有针对Intel CPU的编译器都强制执行/遵循它?我正在编写一个将从C代码调用的汇编函数.我可以为所有编译器假设这个吗?(我x86目前只针对目标)
特别是,我在库接口中获得了以下代码:
typedef enum
{
state1,
state2,
state3,
state4,
state5,
state_error = -1,
} State;
Run Code Online (Sandbox Code Playgroud)
我严格禁止打破ABI.但是,我想添加state6和state7.它会破坏ABI吗?
您可以...
- 将新枚举器附加到现有枚举.
执行:如果这导致编译器为枚举选择更大的底层类型,则会使更改与二进制不兼容.遗憾的是,编译器有一些余地可以选择底层类型,因此从API设计的角度来看,建议添加一个带有显式大值(= 255,= 1 << 15等)的Max ....枚举器来创建一个数值枚举器值的间隔,保证适合所选的基础类型,无论可能是什么.
我尝试使用ubuntu 15.10存储库版本的libmuparser(包libmuparser2v5).用gcc编译工作正常,但不能用clang编译.我深入研究了这个问题,提出了以下最小(非)工作示例和几个问题.
考虑一个带有一个简单类的库,它接受一个string并返回一个string.
testlib.h:
#pragma once
#include <string>
struct Test {
std::string str;
void set(std::string s);
std::string get();
};
Run Code Online (Sandbox Code Playgroud)
testlib.cpp:
#include "testlib.h"
void Test::set(std::string s) {
str = s;
}
std::string Test::get() {
return str;
}
Run Code Online (Sandbox Code Playgroud)
这是用gcc 5.2.1编译为静态库的
g++ -Wall -c testlib.cpp -o testlib-gcc.o
ar rcs libtest-gcc.a testlib-gcc.o
Run Code Online (Sandbox Code Playgroud)
现在编译一个应用程序 main.cpp
#include <iostream>
#include "testlib.h"
int main()
{
Test p;
p.set("Hello!");
std::cout << p.get() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用clang 3.6.2-1使用
clang++ main.cpp -o out-clang …Run Code Online (Sandbox Code Playgroud) arm-none-eabi和arm-linux-gnueabi有什么区别?我知道如何使用它们(一个用于裸机软件,另一个用于打算在Linux上运行的软件)的区别。但是技术背景是什么?
据我所知,我看到了ABI的区别,它类似于API,但在二进制级别。它确保了不同应用程序的互操作性。
但是我真的不了解拥有或没有操作系统会以哪种方式影响我的工具链。我唯一想到的是,在编译裸机软件时,可能必须将库静态链接(对吗?),因为没有操作系统可以动态地提供它们。
我发现与此主题相关的最多页面只是回答了如何使用工具链,但没有回答技术背景。我是机电一体化和嵌入式系统的新学生,所以我在该领域的经验有限。
重复:我正在寻找相同 Visual-C++版本的库之间的ABI兼容性!
我们希望混合和匹配来自不同团队的一些内部C++ DLL - 在不同时间使用不同的项目文件构建.由于构建时间较长,我们确实希望避免大型单片构建,其中每个团队重新编译另一个团队库的源代码.
当消耗C++的DLL 和C++的接口是相当 清楚 的是,你只能这样做,如果所有的DLL与相同的编译器/ Visual Studio的版本编译.
什么对我来说并不很明显是什么,到底需要是相同的,以获得ABI的兼容性.
_DEBUG)和release(NDEBUG)不能混合 - 但是这些链接到不同版本的共享运行时这一事实也很明显./O需要相同的开关 - 优化级别是否会影响ABI兼容性?(我很确定不会.)/EH开关?/volatile:ms|iso......?本质上,我想提出一组(元)数据来与描述它的ABI兼容性的Visual-C++ DLL相关联.
如果存在差异,我现在只关注VS2015.
标题说明了所有.我将为具有默认值的类的成员函数添加一个参数.这个论点属于非平凡的类型.这会破坏ABI吗?假设我的新库版本将会出现M.m.0,并且应该可以作为所有使用的链接应用程序的替代品M.m-1.x.
示例代码:
// These are some classes: base and child : public base
/* Version 1.2.3 */
class foo() {
public:
void do_that_stuff(const std::string a);
}
/* Version 1.3.0 */
class foo() {
public:
void do_that_stuff(const std::string a, const base& b = base());
}
Run Code Online (Sandbox Code Playgroud)
PS:我做了自己的测试,并且它正在运行.只是不能确定
假设Linux上的x86-64 ABI,在C++中的什么条件下结构传递给寄存器中的函数而不是堆栈中的函数?他们在什么条件下返回登记册?课程的答案是否会改变?
如果它有助于简化答案,则可以假设单个参数/返回值而没有浮点值.
最近我读了一些关于Swift 5是ABI Stable的文章(这基本上意味着你不需要在应用程序包中打包应用程序自己的Swift动态库版本),这里有一个令人困惑的部分:
因为Swift将嵌入iOS操作系统中.
现在听起来像Swift Dynamic Library现在可以直接进入iOS.这是否意味着编译Swift 5的Apps将只能在特定的iOS版本上运行?