Uploaded by Wu Allen

How to create a Android SO library dinamically loaded in your FMX projects by Emailx45 mb61025d8d39b66的技术博客 51CTO博客

advertisement
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
学堂
精培
企业培训
CTO训练营
首
关
排行
订阅专
页
注
榜
栏
智能汽车
开源基础软件社区

LeaTech全球CTO领导力峰会
搜索文章、作者

公众号矩阵
创作中心
 写文章
移动端
登录 注册
How to create a Android SO library dinamically loaded in yo
ur FMX projects? by Emailx45
转载
红鱼儿_
红鱼儿_ 2022-04-20 15:37:07
387
15.2万
7
6
文章标签
原创
人气
粉丝
评论
ide
android
java
文章分类
代码人生
阅读数 62
盒子上朋友Emailx45又发布了贴子,在FMX项目中如何建立并使用Android动态库?又是一篇实用的文章,转贴过
1
40
1
3
翻译
转载
关注
收藏
来,同时向他表示感谢!
先看图:
关注
 私信
近期文章
1. Java基础知识点(StringJoiner及Strin…
2.linux最小化安装后添加图形界面
3.linux中python程序复制文件的代码实现
4.IPIDEA带你了解HTTP协议和SOCKS…
5.6,docker基础之---Dockerfile构建redis
https://blog.51cto.com/kinglandsoft/5225729
1/19
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
学堂
精培
企业培训
首
关
排行
订阅专
页
注
榜
栏
https://blog.51cto.com/kinglandsoft/5225729
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
 写文章

创作中心
公众号矩阵
移动端
登录 注册
2/19
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
学堂
精培
企业培训
首
关
排行
订阅专
页
注
榜
栏
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
 写文章

创作中心
公众号矩阵
移动端
登录 注册
Later very searches on internet and almost nothing found, I have solved the question.
First, let's remeber about that a library is, pratically, the same that an executable application. Of course, the speci
allists can define better than me.
The RAD Studio can create library in MSWindows, Linux and macOS platform systems. Just use the wizard do cr
eate it in your IDE:
https://blog.51cto.com/kinglandsoft/5225729
3/19
2023/3/3 晚上7:31
File ->
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
Other
-> New 博客
:
内容精选
首
学堂
关
精培
企业培训
排行
订阅专
榜
栏
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
 写文章

创作中心
公众号矩阵
移动端
登录 注册
Dinamic Library (MSWindows, macOS)
页
Android Service (Android)
注
Here, we can note that there is not a Linux option, but Android is a not a Linux at end?
But this is not the point here.
The point is: What is the difference between a library to MSWindows and Posix systems?
Good point!!!
The point more significant is how the code is called and intepreted by CPU target.
Certainly this matter is beyond my knowledge, and therefore we will leave it to the engineers on duty.
https://blog.51cto.com/kinglandsoft/5225729
4/19
2023/3/3 晚上7:31
51CTO首页
Returning内容精选
to my
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
博客 world学堂
精培 as already
企业培训mentioned
CTO训练营
智能汽车
开源基础软件社区
humble
of knowledge,
above, RAD
Studio can
generate such LeaTech全球CTO领导力峰会
code t

公众号矩阵
移动端
hat will be supported by the target CPU supported by RAD Studio, so there is no need to go into much depth at th
is point.
首
关
排行
订阅专
页
注
榜
栏
 写文章
创作中心
登录 注册
Let's pay attention to the following points that the programmer must obey:
create library file according to desired target CPU
test the code to check for possible design flaws
check the access permissions on the target disk (at least read and write in case of MSWindows, and in Posix, exe
cute permission if necessary)
deploy the library to the target operating system
in the client software, always ask the end user for their consent to access the disk, and later access the library fil
e for dynamic loading.
after executing the tasks proposed by the library, always end the call, that is, freeing the memory consumed by th
e library.
Thus, avoiding memory accumulation and possibly a memory leak when terminating the software.
As RAD Stuido is an advanced programming interface, many of the programmer's tasks are reduced to simple cli
cks and choices on the IDE's screen.
https://blog.51cto.com/kinglandsoft/5225729
5/19
2023/3/3 晚上7:31
This
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
is fine,
however,博客
it makes学堂
the developer
lazy and careless.
Especially
if he is a开源基础软件社区
beginner or has aLeaTech全球CTO领导力峰会
lot of a
内容精选
精培 very 企业培训
CTO训练营
智能汽车

公众号矩阵
移动端
pplications in his domain.
首
关
排行
订阅专
 写文章
创作中心
登录 注册
页the programmer
注
榜
栏 IDE you use.
We must not forget that
is you, not the
We must have it as a working tool, not as an excuse not to reason.
In a popular Brazilian saying, we say:
The rushed eat raw. (those in a hurry don't wait for the rice to be cooked as it should)
Now, on to the code!
Here I will demonstrate a way that will try to demystify the use of the RAD Studio IDE, and, by following, prove tha
t many codes found on the internet, and widely reproduced in many blogs, should not be or at least should be stu
died and used in other ways. shapes.
I will demonstrate that you can create a RAD Studio project file (*.DPR) manually (without using the RAD Studio I
DE). Naturally, some settings I'll do via IDE for the simple fact that RAD Studio creates many auxiliary files on dis
k, and creating them manually is really a karma that I don't want at this point.
https://blog.51cto.com/kinglandsoft/5225729
6/19
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
First I will create the DPR
which will be my library (OS) for Android 64bits.
首 file called
关 "mydprmanuallibrary.dpr",
排行
订阅专
 写文章

创作中心
公众号矩阵
移动端
登录 注册
页
注
榜
栏
For that, I will use Notepad++ (generic file editor) to prove that is not necessary (at all) use the IDE from RAD Stu
dio do create it.
So, the contents of this file will be as follows:
1.
program mydprmanuallibrary;
2.
3.
{$R *.res}
4.
5.
// ---- this code will be added by RAD Studio IDE, ok?
6.
//
------- then, just ignore it for while....
7.
//
uses
8.
//
9.
//
because the auxiliar files used by RAD!
uUnitWithFunctions in 'uUnitWithFunctions.pas';
-----
10.
11.
begin
12.
end.
Pay attention in line with "program mydprmanuallibrary;" ... this is the real difference between a "Library MSWindo
ws" and a "Library to Posix".
--- MSWindows: library mydprmanuallibrary;
https://blog.51cto.com/kinglandsoft/5225729
7/19
2023/3/3 晚上7:31
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
--- Posix:内容精选
program
51CTO首页
mydprmanuallibrary;
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
首 unit with
关my function
排行 in my library
订阅专
Now, I will go create my
1.
unit uUnitWithFunctions;
页
2.
3.
注
榜
 写文章

创作中心
公众号矩阵
移动端
登录 注册
栏
interface
4.
5.
function IncrementThisValue(AValue: integer): integer; cdecl;
6.
7.
exports IncrementThisValue;
8.
9.
implementation
10.
11.
function IncrementThisValue(AValue: integer): integer;
12.
begin
13.
Inc(AValue);
14.
result := AValue;
15.
end;
16.
17.
end.
Now, our library SO Android is almost ready for use. Let's use the IDE to create all auxiliar files and configuration
s necessary for end it.
Auxiliar files to IDE development:
--- mydprmanuallibrary.identcache
--- mydprmanuallibrary.dproj.local
--- mydprmanuallibrary.dproj
https://blog.51cto.com/kinglandsoft/5225729
8/19
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
In your IDE RAD Studio,
file to complete
首 just open
关 the DPR
排行
订阅专 the task
 写文章

创作中心
公众号矩阵
移动端
登录 注册
you need just a little adjust in:
页
注
榜
栏
--- Project -> Options -> Application -> Version Info: 1 or any other value > 0
--- Project -> Options -> Application -> Entitlement List: check the "Secure File Sharing"
--- Project -> Options -> Application -> Use Permissions: check the "read / write external storage" (if you go use i
t... any way, check it)
--- save your project to create the auxiliar files and store it in disk!
Now, all it's ready for use!
Now, you can create your FMX project for your client-app as expected in common use.
Let's create a sample for tests.
On RAD, do that:
--- File -> New - Firemonkey blank project
https://blog.51cto.com/kinglandsoft/5225729
9/19
2023/3/3 晚上7:31
--- add
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
the
requirement
from
内容精选
博客of "permissions"
学堂
精培 user企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
--- add code to load the
catch the 排行
function address,
首library, 关
订阅专and release the library if not necessary any more.
页
注
Here my sample for your test:
榜
 写文章

创作中心
公众号矩阵
移动端
登录 注册
栏
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28
unit uView.FormMain;
interface
uses
System.SysUtils,
System.Types,
System.UITypes,
System.Classes,
System.Variants,
FMX.Types,
FMX.Controls,
FMX.Forms,
FMX.Graphics,
FMX.Dialogs,
FMX.Controls.Presentation,
FMX.StdCtrls,
System.Permissions,
FMX.Memo.Types,
FMX.ScrollBox,
FMX.Memo;
type
TForm1 = class(TForm)
BtnRequestPermissions: TButton;
https://blog.51cto.com/kinglandsoft/5225729
10/19
2023/3/3 晚上7:31
28.
51CTO首页
29.
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
BtnLoadSOandRun:
TButton;
内容精选
博客
学堂
30.
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会

公众号矩阵
移动端
 写文章
创作中心
登录 注册
procedure FormCreate(Sender: TObject);
private
34.
页
注
榜
栏
procedure MyPermissionsHandler(Sender: TObject; const APermissions: TClassicStringDynArray; c
public
36.
37.
CTO训练营
procedure BtnLoadSOandRunClick(Sender: TObject);
32.
35.
企业培训
procedure首BtnRequestPermissionsClick(Sender:
关
排行
订阅专 TObject);
31.
33.
精培
Memo1: TMemo;
{ Public declarations }
end;
38.
39.
40.
var
Form1: TForm1;
41.
42.
implementation
43.
44.
45.
46.
47.
48.
uses
System.IOUtils,
Androidapi.JNI.JavaTypes,
Androidapi.Helpers,
Androidapi.JNI.Os;
49.
50.
{$R *.fmx}
51.
52.
53.
54.
const
MyFileSO: string
= 'libmydprmanuallibrary.so';
MyFuncName: string = 'IncrementThisValue';
55.
56.
57.
58.
var
MyFileSOPath: string;
MyFuncOnLib : function(AValue: integer): integer; cdecl;
59.
60.
procedure TForm1.MyPermissionsHandler(Sender: TObject; const APermissions: TClassicStringDynArray
61.
https://blog.51cto.com/kinglandsoft/5225729
11/19
2023/3/3 晚上7:31
62.
51CTO首页
63.
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
begin
内容精选
64.
精培
企业培训
LeaTech全球CTO领导力峰会

公众号矩阵
移动端
 写文章
创作中心
登录 注册
BtnLoadSOandRun.Enabled
:= 榜
true;
页
注
栏
Memo1.Lines.Add('permissions accepted by user');
end else begin
70.
BtnLoadSOandRun.Enabled := false;
71.
Memo1.Lines.Add('permissions refused by user');
73.
开源基础软件社区
//
begin
68.
72.
智能汽车
CTO训练营
JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE)]) then
67.
69.
学堂
JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE),
{ }
首
关
排行
订阅专
65.
66.
博客
if PermissionsService.IsEveryPermissionGranted([
end;
end;
74.
75.
procedure TForm1.BtnRequestPermissionsClick(Sender: TObject);
76.
begin
77.
PermissionsService.RequestPermissions([
{ }
78.
JStringToString(TJManifest_permission.JavaClass.READ_EXTERNAL_STORAGE),
79.
JStringToString(TJManifest_permission.JavaClass.WRITE_EXTERNAL_STORAGE)], { }
80.
MyPermissionsHandler);
81.
{ }
end;
82.
83.
procedure TForm1.FormCreate(Sender: TObject);
84.
begin
85.
86.
MyFileSOPath := IncludeTrailingPathDelimiter(TPath.GetDocumentsPath) + MyFileSO;
end;
87.
88.
procedure TForm1.BtnLoadSOandRunClick(Sender: TObject);
89.
var
90.
91.
MySOHandle: THandle;
begin
92.
MySOHandle
93.
@MyFuncOnLib := nil;
94.
//
:= 0;
95.
https://blog.51cto.com/kinglandsoft/5225729
12/19
2023/3/3 晚上7:31
51CTO首页
96.
97.
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
//
内容精选
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会

公众号矩阵
移动端
try
98.
Memo1.Lines.Add('trying
SafeLoadLibrary(MyFileSOPath)...
starting...');
首
关
排行
订阅专
99.
//
100.
Memo1.Lines.Add('Lib path: ' + MyFileSOPath);
101.
Memo1.Lines.Add('Lib
' + PWideChar(MyFileSOPath));
页
注 path: 榜
栏
102.
//
103.
(*
 写文章
104.
SafeLoadLibrary simply as a replacement for LoadLibrary.
105.
It has a second parameter witch is used to call SetErrorMode.
106.
That parameter is optional and defaults to SEM_NOOPENFILEERRORBOX which is NOT always what
107.
if the DLL you are loading depends on other DLLs which cannot be loaded, you will get a sys
108.
if not dialog error, not info about the "error" ... is it not?
创作中心
登录 注册
109.
110.
in Posix compilation:
111.
-- LoadLibrary(...), in fact, will calls: dlopen() function
112.
-- GetProcAddress(...), in fact, will calls: dlsym(), dladdr(), dlopne() and dlclose() func
113.
-- FreeLibrary(...), in fact, will calls: dlclose() function
114.
*)
115.
// MySOHandle := SafeLoadLibrary(MyFileSOPath);
116.
MySOHandle := LoadLibrary(PWideChar(MyFileSOPath)); // using Posix function:
117.
//
118.
if (MySOHandle > 0) then
119.
begin
dlopen(....)
120.
Memo1.Lines.Add('MySOHandle = ' + MySOHandle.ToString);
121.
//
122.
@MyFuncOnLib := GetProcAddress(MySOHandle, PWideChar(MyFuncName)); // using Posix function:
123.
//
124.
if Assigned(MyFuncOnLib) then
Memo1.Lines.Add('255 + 1 = ' + MyFuncOnLib(255).ToString)
125.
126.
else
Memo1.Lines.Add('MyFuncOnLib = nil');
127.
128.
129
end
https://blog.51cto.com/kinglandsoft/5225729
13/19
2023/3/3 晚上7:31
129.
51CTO首页
130.
131.
132.
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
else
内容精选
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会

公众号矩阵
移动端
Memo1.Lines.Add('MySOHandle = 0');
finally
首
关
排行
订阅专
 写文章
FreeLibrary(MySOHandle); // using Posix function:
133.
创作中心
登录 注册
dlclose(....)
//
134.
Memo1.Lines.Add('FreeLibrary(MySOHandle)...
done');
页
注
榜
栏
end;
end;
end.
It's all folks!
good fun with this!
这是运行结果:
https://blog.51cto.com/kinglandsoft/5225729
14/19
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
学堂
精培
企业培训
首
关
排行
订阅专
页
注
榜
栏
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
 写文章

创作中心
公众号矩阵
移动端
登录 注册
别忘记发布so文件,如下图:
https://blog.51cto.com/kinglandsoft/5225729
15/19
2023/3/3 晚上7:31
51CTO首页
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
博客
首 赞
学堂
关
精培
企业培训
排行
收藏
上一篇:Cannot fit requested
页 classes
注in a single
榜dex fil…

CTO训练营
订阅专
评论
栏

智能汽车
分享
开源基础软件社区

LeaTech全球CTO领导力峰会
举报
 写文章

创作中心
公众号矩阵
移动端
登录 注册
下一篇:Delphi 格式化代码调整每行的宽度
提问和评论都可以,用心的回复会被更多人看到
评论
相关文章
Emailx45:如何在Android/iOS设备上更改StatusBar颜色?
How to changes the StatusBar color in Android / iOS devices? 作者:Emailx45NOTE: test in your device for effective usable, b…
android
ios
java
Android Coding: Gestures Builder: create your gestures library
Android Coding: Gestures Builder: create your gestures librarySep 18, 2011Gestures Builder: create your gestures libraryGestu…
android
eclipse
android library projects cannot be launched
android library projects cannot be launched;发生这样的问题是因为你把你的项目当成一个库来启动的,解决办法就是现在项目的…
android
其他
https://blog.51cto.com/kinglandsoft/5225729
16/19
2023/3/3 晚上7:31
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
内容精选
51CTO首页
博客
学堂
精培
企业培训
CTO训练营
How to Create an Reusable Components for Your Project
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
In our daily work, we always
and do it again
and again, but how can we create the reusable components fo…
首 write the
关same code
排行
订阅专
Resuable
 写文章

创作中心
公众号矩阵
移动端
登录 注册
Components
页
注
榜
栏
完美解决android library projects cannot be launched
解决办法如下:右键工程根目录->properties左侧选择->android把 is library勾选去掉,不要勾选。
右键
根目录
android
Android library projects cannot be launched解决方法
今天的项目总是报这个问题,解决方法如下将图中的 Is Library前面的对勾去掉,这样问题就解决了
android
android library projects cannot be launched解决办法
properties 在android选项中将 is library中将前面的勾去了
android library proj
其他
android
How does photo library display so many images
To extend on the subject, ...without crashing? I load about 15 full size images from the photo library in UIImageViews and get o…
sed
facebook
iphone
数据
How to create a DLL library in C and then use it with C#
​IntroductionAfter spending some time trying to implement this simple task, I started to search similar code examples over the Int…
c#
c++
ide
.net
sed
SAP UI5 how the ui library theme parameter is loaded
Created by Wang, Jerry, last modified on Apr 09, 2015要获取更多Jerry的原创文章,请关注公众号"汪子熙":
https://blog.51cto.com/kinglandsoft/5225729
17/19
2023/3/3 晚上7:31
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
SAP UI5
UI5
51CTO首页
内容精选
博客
学堂
精培
企业培训
CTO训练营
智能汽车
开源基础软件社区
LeaTech全球CTO领导力峰会
首 and use
关 your排行
订阅专 Link Library (C++)
Walkthrough: Create
own Dynamic
 写文章

创作中心
公众号矩阵
移动端
登录 注册
This step-by-step walkthrough shows how to use the Visual Studio IDE to create your own dynamic link library (DLL) written in …
c++
#include
ide
页 sed
microsoft
注
榜
栏
How to Flash a ROM to Your Android Phone
http://lifehacker.com/how-to-flash-a-rom-to-your-android-phone-30885281Android is great, but sometimes, th...
android
ide
linux
navicat oracle library is not loaded
navicat oracle library is not loaded CreationTime--2018年8月9日19点13分 Author:Marydo
后台开发工具
oracle
重启
ci
How to make local changes on your ui5 library file in Eclipse
.
SAP UI5
ui5
How to Integrate .NET Projects with Jenkins
https://www.swtestacademy.com/jenkins-dotnet-integration/ 8) Unit Tests and Test Coverage Settings Download and extract Op…
xml
学习
How to Leverage Your Market Data to Create Hit Apps (Article mark, translatio
http://blog.appannie.com/chad-mureta-leverage-data/?utm_campaign=weekly-digest&utm_source=hs_email&utm_medium=em…
target
Create
title
blank
What is Favicon.ico and How to Create a Favicon Icon for Your Website?[zz]
https://blog.51cto.com/kinglandsoft/5225729
18/19
2023/3/3 晚上7:31
How to create a Android SO library dinamically loaded in your FMX projects? by Emailx45_mb61025d8d39b66的技术博客_51CTO博客
by Christopher
Heng, ​com/"
thesitewizard.com​
​Some timeCTO训练营
back, I had an智能汽车
email from a 开源基础软件社区
visitor asking me howLeaTech全球CTO领导力峰会
I ma…
51CTO首页
内容精选
博客 target="_top">​
学堂
精培
企业培训
ico
ide
sed
firefox
首
公众号矩阵

移动端
safari
关
排行
订阅专
 写文章
创作中心
登录 注册
How to create and use SDCard image for Android emulator
为了学习使用Android新的组件,先得为Android
页
注
榜emulator虚拟一个SD卡。下面就把我的实验工作记录一下(本实验默认已经配…
栏
模拟器
移动开发
休闲
Android
SD卡镜像
the rendering library is more recent than your version of android studio
近期更新了自己Android Studio中的SDK到最新版本号,AS的一部分配置改动了。然后 在打开布局文件的时候 会出现 渲染错误 …
版本号
android
布局文件
made
友情链接
Copyright © 2005-2023 51CTO.COM 版权所有 京ICP证060544号
https://blog.51cto.com/kinglandsoft/5225729
关于我们
开源基础软件社区
51CTO学堂
官方博客
全部文章
热门标签
班级博客
51CTO
汽车开发者社区
了解我们
在线客服
网站地图
意见反馈
19/19
Download