99.9RMB 悬赏一技术支持

2021-02-26 11:00:27 +08:00
 phpIsNumberOne
概述:

使用 C 打包为 Android 的 C-shar(so)动态链库,然后使用 Fltter 的 ffi 调用。现在我实现了函数为 int 类型的相互调用,但是 string(*char)始终有问题。

要求:

将 C 程序打包为 so 动态链库,并能在 Flutter 项目上正常使用,仅 Android 即可,使用 CMake ; C 程序:

#include <stdio.h>
#include <stdlib.h>
int Hello(){
    return 233;
}

char *World(){
    char *r = "1234";
    return r;
}

char *Test(char *str)
{
    return str;
}
说明:
相关资料:
6976 次点击
所在节点    程序员
40 条回复
oxromantic
2021-02-26 14:27:41 +08:00
楼上一群冷嘲热讽的不知道有没有认真看代码, 至少楼主的例子我用 flutter 跑了下是可以传到 flutter 端的

楼主的例子是 literals string, 本来就不需要栈上分配内存, 直接 return 又如何?

不知道楼主 flutter 端是怎么写的, 至少我是这样可以取到的:

#include <stdint.h>
#include <string.h>

extern "C" __attribute__((visibility("default"))) __attribute__((used))
char* native_add(int32_t x, int32_t y) {
return "12345";
}

final Pointer<Utf8> Function(int x, int y) nativeAdd = nativeAddLib
.lookup<NativeFunction<Pointer<Utf8> Function(Int32, Int32)>>(
"native_add")
.asFunction();

Text('Running on: $_platformVersion ${Utf8.fromUtf8(nativeAdd(3, 3))}\n')
Visitor233
2021-02-26 14:31:24 +08:00
@hanxiV2EX 确实,学习了。
Anshi
2021-02-26 14:32:51 +08:00
悬赏 99.9 为什么会收到冷嘲热讽,是属于一个文化界限问题,要么一杯咖啡,对方当交个朋友,而选中帮你,要么完全不提供回馈,直接真诚提问,对方这是公益性质的帮你,如果选择一个实际的数字量化,那就需要好好讨论,帮你这个事情变得复杂,它到底值多少钱,多了,显得势力,少了,不划算,变成了人性的问题。
Ritter
2021-02-26 15:14:23 +08:00
100 块不少了 可惜我不会
NasirQ
2021-02-26 15:31:39 +08:00
抛开其他,我觉得楼主出价有问题。首先所谓 "99.9" "9.9" 这样子定价,是商家为了满足顾客的省钱心里做的定价策略。然而楼主是在寻求技术支持。这里建议改为 0.1k 或者 0.1011k,这样二进制形式的数字更能吸引人 [dog]
daoyouma
2021-02-26 15:47:35 +08:00
10 分钟能解答 我不介意 关键 我不会
yolee599
2021-02-26 20:34:54 +08:00
char *r = "1234"; 要改成 const char *r = "1234";
yolee599
2021-02-26 20:38:07 +08:00
@yolee599 说错了要改成 static const char *r = "1234";
aheadlead
2021-02-26 21:00:48 +08:00
………………………楼上这

我来回答一下吧。楼主你在 World() 里定义的变量 char *r 是在 World() 这次函数调用的栈帧里的。
World() 函数返回后,栈帧弹出,char *r 本身所占据的 8 字节内存就不应该访问了。

虽然你仍然有可能能访问到,但这属于 undefined behavior 。
我对 Flutter 一无所知,但有可能是就是你访问了不该访问的内存(比如提示 memory access violation 、segmentation fault 之类的)。

至于你说 Test() 函数也会闪退。Test() 函数本身没有任何问题(只是没啥意义),可能和你的用法有关。楼主要是不嫌麻烦的话,把代码放到 github 或者 gist/pastebin 上,我可以一看。
aheadlead
2021-02-26 21:04:23 +08:00
补充一下,char *r 所指向的内存是在 rodata 段,这块区域的内存可以随意访问。
导致访问出错的不是 r 指向的内存,而是访问 r 本身。

FYR: https://en.wikipedia.org/wiki/Data_segment
aheadlead
2021-02-26 21:08:22 +08:00
hanssx
2021-02-27 09:37:13 +08:00
@aheadlead 请教个问题,我对 c 语言也不熟,我 World()函数返回的应该是"1234"的内存地址吧?"1234"是在堆上分配的吗?如果是的话,World()函数返回值应该还能索引到"1234"这块内存吧?
aheadlead
2021-02-27 09:46:58 +08:00
@hanssx #31 你这么一说还真是。。。看来好几年没写 C 还犯错了,糗大了

你说的是正确的,昨天我发的那个代码还多此一举了,抱歉浪费各位时间。

准确的说,楼主位的代码是不会造成我说的那种内存错误。楼主可以抓个 bugreport 看下 native 的 log 是什么。
realpg
2021-02-27 11:11:31 +08:00
提问良好,字多并不啰嗦,值得鼓励
realpg
2021-02-27 11:15:00 +08:00
@NasirQ #25
真的 99.9 这种会遭人反感的

但是 0.0001M 估计会有码农开心的愿意的
cz5424
2021-02-27 11:51:32 +08:00
建议楼主看一下 C 语言的指针部分,函数内分配的内存不要再返回出去,容易内存泄露
caiyue1993
2021-02-27 14:30:06 +08:00
阴阳怪气的人真多啊,“请尽量让自己的恢复能够对别人有帮助”
taogen
2021-02-27 17:47:18 +08:00
99.9 充满资本的铜臭味道
phpIsNumberOne
2021-02-27 17:54:49 +08:00
找到问题了,主要是我更新代码后使用得是热重载(Hot reload),和想象的不太一样,so 文件好像并没有更新,致使我写了正确的代码也没有正确的反馈;将 APP 卸载重新编译即可。

至于 C 内存的问题,并没有考虑那么多,只想先跑通再说;而且我实际也不是用的 C,而是用的 go(CGO);使用 C 尝试就是因为没有给我正常的反馈,还以为是 CGO 的问题。

再补充两点:
动态库的名称应该以 lib 开头,否则项目以 release 运行时会找不到;
go 函数中不能写 defer C.free(unsafe.Pointer(r))释放内存,应该 dart 取到值后再释放。
phpIsNumberOne
2021-02-27 17:55:56 +08:00
@hanxiV2EX
@oxromantic
@aheadlead
感谢你们的热心解答

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/756414

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX