首页 \ 问答 \ 如何将.a C静态库添加到Xcode并在那里使用它?(How to add .a C static library to Xcode and use it there? [duplicate])

如何将.a C静态库添加到Xcode并在那里使用它?(How to add .a C static library to Xcode and use it there? [duplicate])

这个问题在这里已有答案:

我有一个用arm7-gcc编译的静态C库,我想在我的iOS项目中使用它。 我把它添加到项目但我无法弄清楚如何使用它。


This question already has an answer here:

I have a static C library compiled with arm7-gcc and i want to use it in my iOS project. i added it to project but i can't figure out how to use it.


原文:https://stackoverflow.com/questions/11830434
更新时间:2021-10-28 18:10

最满意答案

首先是一个大警告: “不安全必须死” http://blog.takipi.com/still-unsafe-the-major-bug-in-java-6-that-turned-into-a-java-9-feature/

一些先决条件

static class DataHolder {
    int i1;
    int i2;
    int i3;
    DataHolder d1;
    DataHolder d2;
    public DataHolder(int i1, int i2, int i3, DataHolder dh) {
        this.i1 = i1;
        this.i2 = i2;
        this.i3 = i3;
        this.d1 = dh;
        this.d2 = this;
    }
}

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

DataHolder dh1 = new DataHolder(11, 13, 17, null);
DataHolder dh2 = new DataHolder(23, 29, 31, dh1);

基础

要获取字段(i1)的偏移量,可以使用以下代码:

Field fi1 = DataHolder.class.getDeclaredField("i1");
long oi1 = unsafe.objectFieldOffset(fi1);

并且可以访问实例dh1的字段值

System.out.println(unsafe.getInt(dh1, oi1)); // will print 11

您可以使用类似的代码来访问对象引用(d1):

Field fd1 = DataHolder.class.getDeclaredField("d1");
long od1 = unsafe.objectFieldOffset(fd1);

你可以使用它从dh2获取对dh1的引用:

System.out.println(dh1 == unsafe.getObject(dh2, od1)); // will print true

现场排序和对齐

要获取对象的所有声明字段的偏移量:

for (Field f: DataHolder.class.getDeclaredFields()) {
    if (!Modifier.isStatic(f.getModifiers())) {
        System.out.println(f.getName()+" "+unsafe.objectFieldOffset(f));
    }
}

在我的测试中,似乎JVM按其认为合适的方式重新排序字段(即添加字段可以在下次运行时产生完全不同的偏移)

本机内存中的对象地址

重要的是要理解以下代码迟早会使JVM崩溃,因为垃圾收集器会随机移动您的对象,而无法控制何时以及为什么会发生这种情况。

另外,了解以下代码依赖于JVM类型(32位与64位)以及JVM的某些启动参数(即在64位JVM上使用压缩oops)非常重要。

在32位VM上,对对象的引用与int具有相同的大小。 那么如果你调用int addr = unsafe.getInt(dh2, od1));你会得到什么? 而不是unsafe.getObject(dh2, od1)) ? 它可能是对象的原生地址吗?

咱们试试吧:

System.out.println(unsafe.getInt(null, unsafe.getInt(dh2, od1)+oi1));

将按预期打印出11

在没有压缩oops的64位VM上(-XX:-UseCompressedOops),您需要编写

System.out.println(unsafe.getInt(null, unsafe.getLong(dh2, od1)+oi1));

在具有压缩oops的64位VM(-XX:+ UseCompressedOops)上,事情有点复杂。 此变体具有32位对象引用,通过将它们乘以8L转换为64位地址:

System.out.println(unsafe.getInt(null, 8L*(0xffffffffL&(dh2, od1)+oi1));

这些访问有什么问题

问题是垃圾收集器和此代码。 垃圾收集器可以随意移动对象。 由于JVM知道它的对象引用(局部变量dh1和dh2,这些对象的字段d1和d2),它可以相应地调整这些引用,你的代码永远不会注意到。

通过将对象引用提取到int / long变量中,可以将这些对象引用转换为原始值,这些原始值恰好具有与对象引用相同的位模式,但垃圾收集器不知道这些是对象引用(它们可能是由也是一个随机发生器),因此在移动物体时不会调整这些值。 因此,一旦触发了垃圾收集周期,您提取的地址就不再有效,并且尝试访问这些地址的内存可能会立即使您的JVM崩溃(好的情况),或者您可能在没有现场注意的情况下丢弃您的内存(坏的)案件)。


First a big warning: “Unsafe must die” http://blog.takipi.com/still-unsafe-the-major-bug-in-java-6-that-turned-into-a-java-9-feature/

Some prerequisites

static class DataHolder {
    int i1;
    int i2;
    int i3;
    DataHolder d1;
    DataHolder d2;
    public DataHolder(int i1, int i2, int i3, DataHolder dh) {
        this.i1 = i1;
        this.i2 = i2;
        this.i3 = i3;
        this.d1 = dh;
        this.d2 = this;
    }
}

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);

DataHolder dh1 = new DataHolder(11, 13, 17, null);
DataHolder dh2 = new DataHolder(23, 29, 31, dh1);

The basics

To get the offset of a field (i1), you can use the following code:

Field fi1 = DataHolder.class.getDeclaredField("i1");
long oi1 = unsafe.objectFieldOffset(fi1);

and the access the field value of instance dh1 you can write

System.out.println(unsafe.getInt(dh1, oi1)); // will print 11

You can use similar code to access an object reference (d1):

Field fd1 = DataHolder.class.getDeclaredField("d1");
long od1 = unsafe.objectFieldOffset(fd1);

and you can use it to get the reference to dh1 from dh2:

System.out.println(dh1 == unsafe.getObject(dh2, od1)); // will print true

Field ordering and alignment

To get the offsets of all declared fields of a object:

for (Field f: DataHolder.class.getDeclaredFields()) {
    if (!Modifier.isStatic(f.getModifiers())) {
        System.out.println(f.getName()+" "+unsafe.objectFieldOffset(f));
    }
}

On my test it seems that the JVM reorders fields as it sees fit (i.e. adding a field can yield completely different offsets on the next run)

An Objects address in native memory

It's important to understand that the following code is going to crash your JVM sooner or later, because the Garbage Collector will move your objects at random times, without you having any control on when and why it happens.

Also it's important to understand that the following code depends on the JVM type (32 bits versus 64 bits) and on some start parameters for the JVM (namely, usage of compressed oops on 64 bit JVMs).

On a 32 bit VM a reference to an object has the same size as an int. So what do you get if you call int addr = unsafe.getInt(dh2, od1)); instead of unsafe.getObject(dh2, od1))? Could it be the native address of the object?

Let's try:

System.out.println(unsafe.getInt(null, unsafe.getInt(dh2, od1)+oi1));

will print out 11 as expected.

On a 64 bit VM without compressed oops (-XX:-UseCompressedOops), you will need to write

System.out.println(unsafe.getInt(null, unsafe.getLong(dh2, od1)+oi1));

On a 64 bit VM with compressed oops (-XX:+UseCompressedOops), things are a bit more complicated. This variant has 32 bit object references that are turned into 64 bit addresses by multiplying them with 8L:

System.out.println(unsafe.getInt(null, 8L*(0xffffffffL&(dh2, od1)+oi1));

What is the problem with these accesses

The problem is the Garbage Collector together with this code. The Garbage Collector can move around objects as it pleases. Since the JVM knows about it's object references (the local variables dh1 and dh2, the fields d1 and d2 of these objects) it can adjust these references accordingly, your code will never notice.

By extracting object references into int/long variables you turn these object references into primitive values that happen to have the same bit-pattern as an object reference, but the Garbage Collector does not know that these were object references (they could have been generated by a random generator as well) and therefore does not adjust these values while moving objects around. So as soon as a Garbage Collection cycle is triggered your extracted addresses are no longer valid, and trying to access memory at these addresses might crash your JVM immediately (the good case) or you might trash your memory without noticing on the spot (the bad case).

相关问答

更多
  • 欢迎使用C ++。 您正在复制您关心的值,但不会复制终止的'\ 0'字符。 假设x有效(即:x> 3且x <= sizeof(缓冲区)),您可以说: output[x - 2] = '\0'; 在调用memcpy()你应该得到你所期望的。 但是:当你处理这样的通信和缓冲时,你需要小心并检查所有内容。 Welcome to C++. You are copying the values you care about but not the terminating '\0' character. Assumi ...
  • memcpy可能是您可以在内存中复制字节的最快方法。 如果你需要更快的东西 - 试着找出一种不复制东西的方法,例如只交换指针,而不是数据本身。 memcpy is likely to be the fastest way you can copy bytes around in memory. If you need something faster - try figuring out a way of not copying things around, e.g. swap pointers only, ...
  • 这适用于反向复制int s: void reverse_intcpy(int *restrict dst, const int *restrict src, size_t n) { size_t i; for (i=0; i < n; ++i) dst[n-1-i] = src[i]; } 就像memcpy() , dst和src指向的区域不能重叠。 如果你想在原地逆转: void reverse_ints(int *data, size_t n) { size ...
  • sizeof(a)是数组a的总大小。 例如,在 int a[3]; printf("%d", sizeof(a)); sizeof a在大多数系统上都是12 (因为int通常是4个字节,你有3个)。 memcpy不知道a是一个数组。 它只知道指向一些内存地址,所以你必须告诉它要传递多少字节。 大多数地方都将memcpy的签名描述为: void *memcpy(void *dst, const void *src, size_t nbytes) sizeof(a) is the total size of ...
  • 可以做些什么来看这个效果 编译并运行此代码: void dump5(char *str); int main() { char s[5]={'s','a','\0','c','h'}; char membuff[5]; char strbuff[5]; memset(membuff, 0, 5); // init both buffers to nulls memset(strbuff, 0, 5); strcpy(strbuff,s); me ...
  • 我并不完全惊讶,你的例子没有表现出奇怪的行为。 尝试将str1复制到str1+2 ,看看会发生什么。 (实际上可能没有区别,取决于编译器/库)。 一般来说,memcpy是以简单(但是快速的方式)实现的。 简单来说,它只是循环数据(按顺序),从一个位置复制到另一个位置。 这可能会导致源被读取时被覆盖。 Memmove做更多的工作,以确保它正确处理重叠。 编辑: (不幸的是,我找不到体面的例子,但这些会做)。 对比此处显示的memcpy和memmove实现。 memcpy只是循环,而memmove执行测试以确定 ...
  • 首先是一个大警告: “不安全必须死” http://blog.takipi.com/still-unsafe-the-major-bug-in-java-6-that-turned-into-a-java-9-feature/ 一些先决条件 static class DataHolder { int i1; int i2; int i3; DataHolder d1; DataHolder d2; public DataHolder(int i1, int i ...
  • memcpy通常以原始速度编码。 它不会是线程安全的。 如果你需要这个,你需要在关键部分执行memcpy调用或使用其他的信号机制。 take_mutex(&mutex); memcpy(dst, src, count); yield_mutex(&mutex); memcpy is typically coded for raw speed. It will not be thread safe. If you require this, you need to perform the memcpy ca ...
  • strlen只计算没有终止符'\ 0'的字符。 没有这个终结符printf不知道字符串的结尾。 解决方案:memcpy(s,a,(strlen(a)+1)); strlen does only count the chars without the terminator '\0'. Without this terminator printf does not know the end od the string. Solution: memcpy(s,a,(strlen(a)+1));
  • 字符串常量的其余部分被忽略,好像它不在那里。 memcpy一旦达到size字节就会停止。 请注意,尽管将大于size的内存块传递给memcpy是安全的,但传递较短的块会触发未定义的行为。 例如,如果传递少于九个字符的字符串, memcpy会将无效字符复制到字符串末尾之后的myArray 。 The rest of the string constant gets ignored, as if it's not there. memcpy stops as soon as it reaches size by ...

相关文章

更多

最新问答

更多
  • 您如何使用git diff文件,并将其应用于同一存储库的副本的本地分支?(How do you take a git diff file, and apply it to a local branch that is a copy of the same repository?)
  • 将长浮点值剪切为2个小数点并复制到字符数组(Cut Long Float Value to 2 decimal points and copy to Character Array)
  • OctoberCMS侧边栏不呈现(OctoberCMS Sidebar not rendering)
  • 页面加载后对象是否有资格进行垃圾回收?(Are objects eligible for garbage collection after the page loads?)
  • codeigniter中的语言不能按预期工作(language in codeigniter doesn' t work as expected)
  • 在计算机拍照在哪里进入
  • 使用cin.get()从c ++中的输入流中丢弃不需要的字符(Using cin.get() to discard unwanted characters from the input stream in c++)
  • No for循环将在for循环中运行。(No for loop will run inside for loop. Testing for primes)
  • 单页应用程序:页面重新加载(Single Page Application: page reload)
  • 在循环中选择具有相似模式的列名称(Selecting Column Name With Similar Pattern in a Loop)
  • System.StackOverflow错误(System.StackOverflow error)
  • KnockoutJS未在嵌套模板上应用beforeRemove和afterAdd(KnockoutJS not applying beforeRemove and afterAdd on nested templates)
  • 散列包括方法和/或嵌套属性(Hash include methods and/or nested attributes)
  • android - 如何避免使用Samsung RFS文件系统延迟/冻结?(android - how to avoid lag/freezes with Samsung RFS filesystem?)
  • TensorFlow:基于索引列表创建新张量(TensorFlow: Create a new tensor based on list of indices)
  • 企业安全培训的各项内容
  • 错误:RPC失败;(error: RPC failed; curl transfer closed with outstanding read data remaining)
  • C#类名中允许哪些字符?(What characters are allowed in C# class name?)
  • NumPy:将int64值存储在np.array中并使用dtype float64并将其转换回整数是否安全?(NumPy: Is it safe to store an int64 value in an np.array with dtype float64 and later convert it back to integer?)
  • 注销后如何隐藏导航portlet?(How to hide navigation portlet after logout?)
  • 将多个行和可变行移动到列(moving multiple and variable rows to columns)
  • 提交表单时忽略基础href,而不使用Javascript(ignore base href when submitting form, without using Javascript)
  • 对setOnInfoWindowClickListener的意图(Intent on setOnInfoWindowClickListener)
  • Angular $资源不会改变方法(Angular $resource doesn't change method)
  • 在Angular 5中不是一个函数(is not a function in Angular 5)
  • 如何配置Composite C1以将.m和桌面作为同一站点提供服务(How to configure Composite C1 to serve .m and desktop as the same site)
  • 不适用:悬停在悬停时:在元素之前[复制](Don't apply :hover when hovering on :before element [duplicate])
  • 常见的python rpc和cli接口(Common python rpc and cli interface)
  • Mysql DB单个字段匹配多个其他字段(Mysql DB single field matching to multiple other fields)
  • 产品页面上的Magento Up出售对齐问题(Magento Up sell alignment issue on the products page)