C++是一种较为基础的、难度较高的编程语言。尽管如此,它在多平台开发领域却有着不可替代的作用。这一点确实值得深入研究和探讨。
C++的底层基础与相对难度
├── CMakeLists.txt
├── android
│ ├── build.gradle
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java/com/cross/Cross.java
│ └── cpp
│ ├── include
│ ├── cross.cpp
│ └── CMakeLists.txt
├── cross.podspec
├── ios
│ └── Classes
│ ├── Cross.h
│ └── Cross.mm
├── src
│ └── url_signature
│ ├── include/url_signature.h
│ ├── url_signature.cpp
│ └── CMakeLists.txt
├── third_party
│ ├── cxxurl
│ │ ├── include
│ │ ├── src
│ │ └── CMakeLists.txt
│ └── hash
│ ├── include
│ ├── src
│ └── CMakeLists.txt
├── test
│ ├── gtest
│ │ ├── include
│ │ ├── src
│ │ └── CMakeLists.txt
│ ├── main.cpp
│ └── CMakeLists.txt
├── example
│ ├── android #省略
│ └── ios #省略
├── build.gradle
├── gradle.properties
├── settings.gradle
C++靠近硬件,这表示它能更直接地操控计算机资源。众多操作系统的核心部分,比如内核和驱动,通常是用C或C++编写的。这门语言的学习难度较大,数据类型繁多,而且内存管理需要开发者亲自处理。如果在编程过程中稍有不慎,就可能出现内存泄露等问题。然而,正是这种接近底层的特性,让它在性能要求极高的场合下发挥着不可替代的作用。
├── CMakeLists.txt
├── include
│ └── json
│ ├── reader.h
│ ├── value.h
│ └── writer.h
└── src
├── json_reader.cpp
├── json_value.cpp
└── json_writer.cpp
与其他高级编程语言,比如Java相比,Java具备垃圾回收功能,这大大减轻了开发者对内存管理的负担。反观C++,开发者需独立确保程序内存的安全,这要求他们具备更丰富的知识和实践经验。
# 设置cmake版本要求
cmake_minimum_required(VERSION 3.10.2)
# 定义库的名字
project(jsoncpp)
# 定义需要参与编译的源文件
add_library(${PROJECT_NAME} src/json_reader.cpp src/json_value.cpp src/json_writer.cpp)
# 定义需要暴露的头文件
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
设计思想的参考依据
C++的设计理念或许借鉴了成功的工程结构。这样的理念有利于打造逻辑明确、模块划分得当的软件项目。在实际开发过程中,以CMake等构建工具为支撑是普遍现象。比如,在一些大型系统级软件的开发中,凭借可靠的设计理念以及强大的构建工具,能够实现高效且稳定的开发过程。
cmake_minimum_required(VERSION 3.10.2)
project(cpp-android-ios-example)
set(CMAKE_CXX_STANDARD 17)
add_subdirectory(third_party/hash)
add_subdirectory(third_party/cxxurl)
add_subdirectory(src/url_signature)
if (ANDROID)
add_subdirectory(android/src/main/cpp)
else ()
add_subdirectory(test/gtest)
add_subdirectory(test)
endif ()
这种设计理念在多平台联合开发领域也有所体现。在跨平台开发过程中,各个平台都有各自的规范和技术特性。C++凭借其独特的设计理念,能在不同平台上进行适度的调整,以更好地支持整个系统的构建。同时,它为开发者提供了一种通用的开发思路。
统一的目录结构优势
externalNativeBuild {
cmake {
path "../CMakeLists.txt" // 这里需要指向项目根目录的 CMakeLists.txt
version "3.10.2"
}
}
在这个项目里,无论是使用第三方库还是编写自己的代码,保持一致的目录结构至关重要。比如库中的文本文件和源代码目录。举个例子,在大型游戏开发项目中,若各个模块缺乏统一的结构,随着项目体量的增大,代码的维护和管理工作将会变得异常困难。
cmake_minimum_required(VERSION 3.10.2)
set(CMAKE_CXX_STANDARD 14)
project(url_signature)
add_library(${PROJECT_NAME} url_signature.cpp)
target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(${PROJECT_NAME} cxxurl hash)
使用.txt文件来标明头文件和参与编译的源码文件,各部分责任清晰。个人开发者或团队在开发时,查找、修改和编译特定代码,都能依照这一规定顺畅进行。
根目录的.txt的关键作用
├── build.gradle
├── gradle.properties
├── settings.gradle
└── android
├── build.gradle
└── src/main
├── AndroidManifest.xml
├── cpp
│ ├── CMakeLists.txt
│ └── native-lib.cpp
└── java/com/cross/Cross.java
根目录下的.txt文件与各个子项目紧密相连,这一点极为关键。在不同的使用情境中,它会产生不同的影响。比如,在转换成aar文件的过程中,如果关联不正确,可能会误将多余的代码包含进去。因此,根据不同情况编写脚本变得十分必要。在特定的开发环境中,我们必须仔细挑选需要包含的C++代码,并将测试代码排除在外。
此外,按照/build.定义的.txt文件路径,必须指向根目录下的.txt文件。这一规定确保了项目整体结构的完整,便于准确连接各个子项目,从而使整个项目能够正常运行。
apply plugin: 'com.android.library'
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
minSdkVersion 16
targetSdkVersion 30
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
// 这里需要指向项目根目录的 CMakeLists.txt 文件
path "../CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
}
子项目的引用操作示例
cmake_minimum_required(VERSION 3.10.2)
project("cross")
include_directories(export_include)
add_library(${PROJECT_NAME} SHARED cross.cpp)
find_library(log-lib log)
target_link_libraries(${PROJECT_NAME} ${log-lib} url_signature)
以src//.txt为例,这展示了在子项目中添加依赖时,项目间能够轻松实现相互引用。在真实的项目协作中,多个子项目间往往需要功能或数据的交互。这种简便的引用手段,使得不同开发者负责的子项目能够高效地连接和互动。
#include
#include
#include "url_signature.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_com_cross_Cross_signatureUrl(JNIEnv *env, jclass clazz, jstring j_url) {
const char *url = env->GetStringUTFChars(j_url, JNI_FALSE);
auto result = env->NewStringUTF(SignatureUrl(url).c_str());
env->ReleaseStringUTFChars(j_url, url);
return result;
}
引用这种模式有助于提升开发速度,降低代码的重复。例如,在企业应用的开发过程中,各个业务逻辑模块可能被划分为若干个子项目。借助这种便捷的引用手段,可以有效地将整个系统整合,同时确保每个子项目保持各自的独立性。
项目特殊的目录布局及理由
package com.cross;
public class Cross {
static {
System.loadLibrary("cross");
}
public static native String signatureUrl(String url);
}
项目里的文件组织形式,在根目录下设置了build、.和.等文件,它们有特定的排列方式。这是由于在开发过程中,存在一定的限制,使得我们无法指定上级文件。若这些文件放置在错误的位置,比如ios目录下,就会造成无法将src和的源文件正确关联的问题。
Cross类作为OC与C++之间的桥梁,在项目架构中扮演着至关重要的角色。它使得iOS与C++能够实现有效沟通。此外,这种接口对于开发跨平台应用具有显著的促进作用。
我想了解一下,在大家的软件开发过程中,是否遇到过和C++跨平台集成相似的技术挑战?如果有的话,欢迎在评论区分享您的经验,或者对这篇文章点赞和转发。
├── cross.podspec
├── ios
│ └── Classes
│ ├── Cross.h
│ └── Cross.mm
Pod::Spec.new do |s|
s.name = 'cross'
s.version = '0.0.1'
s.summary = 'cross library'
s.description = 'Cross library'
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
# 设置源文件,切记不要把测试代码包含进来
s.source_files = 'ios/Classes/**/*','third_party/**/*.{cc,cpp,h}','src/**/*.{cc,cpp,h}'
# 暴露头文件,否则引用该spec的项目无法找到头文件
s.public_header_files = 'ios/Classes/**/*.h','src/url_signature/include/*.h'
s.platform = :ios, '8.0'
# 必须配置HEADER_SEARCH_PATHS属性,是否会导致项目中C++找不到头文件
s.xcconfig = {
'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}/third_party/cxxurl/include/" "${PODS_TARGET_SRCROOT}/third_party/hash/include/" "${PODS_TARGET_SRCROOT}/src/url_signature/include/"'
}
end