欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Flutter應(yīng)用Windows平臺接入實(shí)踐詳解

 更新時(shí)間:2023年02月02日 15:47:28   作者:閑魚技術(shù)?慕柯  
這篇文章主要為大家介紹了Flutter應(yīng)用Windows平臺接入實(shí)踐詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

Windows應(yīng)用開發(fā)有著較為豐富和多樣的技術(shù)選型。C#/WPF 這種偏Native的閉源方案,目前開發(fā)人員相對比較小眾了。C++/QT 的跨平臺框架,C++對于GUI開發(fā)來說上手會更難。JavaScript/CEF/Electron 基于Chromium 的跨端框架,使用前端技術(shù)棧來構(gòu)建桌面應(yīng)用,性能會略低一些??偠灾饔兴L,有一點(diǎn)可以確定的是,跨端能力成為了選型的重要考量。

Flutter從誕生之初起,其核心目標(biāo)就是跨平臺,不僅僅支持Android和iOS的移動端設(shè)備,同時(shí)包括桌面端和Web端。隨著2022年2月Flutter 2.10的推出,也帶來了首個(gè)支持Windows平臺的穩(wěn)定版本。基于Flutter的跨平臺特性,移動端或Web端的Flutter應(yīng)用也能夠在Windows系統(tǒng)上運(yùn)行,Windows應(yīng)用開發(fā)者能夠享受到Flutter開發(fā)帶來的便利和生產(chǎn)力上的提升,同時(shí)移動端開發(fā)者也能夠快速上手Windows應(yīng)用開發(fā)了。

Windows平臺接入

在進(jìn)一步探索和預(yù)演之后,通過Flutter的能力,可以很方便地將移動端的業(yè)務(wù)模塊遷移至PC端,盡可能地實(shí)現(xiàn)一碼多端,降低業(yè)務(wù)維護(hù)成本,以此為出發(fā)點(diǎn),進(jìn)行了Windows平臺的接入。

閑魚App已經(jīng)在Android和iOS平臺上有了多年的積累,并且采用了Native和Flutter混合的技術(shù)方案,F(xiàn)lutter和Native相輔相成,共同組成了App的完整生態(tài)。如果想要讓Flutter相關(guān)的模塊在Windows平臺上運(yùn)行,那就需要讓W(xué)indows平臺補(bǔ)齊Android和iOS平臺提供給Flutter的能力。比如通過Platform Channel提供給Flutter側(cè)相關(guān)的Native能力,通過Platform View將Native視圖嵌入到Flutter頁面中,都需要在Windows平臺上進(jìn)行重新開發(fā)。

Windows平臺通過Plugin或FFI的方式提供相關(guān)能力,需要使用C++編寫相關(guān)的平臺代碼。如果Plugin的代碼可以自閉環(huán),即所有C++代碼都可以在Plugin內(nèi)編寫完成,那這個(gè)Plugin可以單獨(dú)抽成一個(gè)Dart庫。但是如果Plugin的代碼需要復(fù)用其他Plugin或者主工程的C++代碼,粗暴一點(diǎn)就是拷貝代碼,或者通過CMakeLists來控制相互之間的依賴關(guān)系,通過find_package來完成頭文件和庫文件的鏈接。一旦依賴關(guān)系比較復(fù)雜,CMakeLists就會變得臃腫,依賴關(guān)系發(fā)生變化時(shí),也會牽一發(fā)而動全身。隨著系統(tǒng)復(fù)雜度的提升,開發(fā)人員的增加,模塊之間相互耦合在一起,單一模塊的修改都會影響到所有模塊。

針對上述的問題,對于底層的模塊化設(shè)計(jì),梳理了需要遵循的設(shè)計(jì)原則:

  • 單一職責(zé)原則:一個(gè)模塊維護(hù)一個(gè)單一的主要功能,劃清模塊間的職責(zé)邊界;
  • 開閉原則:模塊應(yīng)該對擴(kuò)展開放,對修改關(guān)閉。用抽象構(gòu)建框架,用實(shí)現(xiàn)填充細(xì)節(jié),通過擴(kuò)展實(shí)體來實(shí)現(xiàn)變化,避免修改代碼來實(shí)現(xiàn)擴(kuò)展。
  • 迪米特法則:最少知道原則,對依賴的模塊知道的越少越好,模塊除了對外暴露的方法,其他實(shí)現(xiàn)細(xì)節(jié)都隱藏在內(nèi)部。
  • 接口隔離原則:只依賴需要的接口,模塊之間提供最小的接口實(shí)現(xiàn)依賴關(guān)系。
  • 依賴倒置原則:依賴抽象,不依賴具體細(xì)節(jié),模塊之間需要依賴抽象的架構(gòu),而非具體的模塊細(xì)節(jié)。

首先基于上述的設(shè)計(jì)原則,制定了模塊化拆解的XModule方案,依據(jù)職責(zé)來劃分模塊,設(shè)計(jì)對外暴露的抽象接口,抽象接口保持最小化原則,完成接口實(shí)現(xiàn),編譯出模塊的動態(tài)鏈接庫DLL,依賴到主工程并放置到特定目錄,運(yùn)行時(shí)通過插件機(jī)制進(jìn)行動態(tài)加載。

其次針對模塊化帶來的依賴管理復(fù)雜的問題,引入了vcpkg的依賴管理方案,通過清單模式便捷地管理各個(gè)模塊,可以自動引入間接依賴,并且版本沖突問題也不復(fù)存在了。
結(jié)合XModule和vcpkg之后,最終形成了下面的結(jié)構(gòu),后面將詳細(xì)展開。

模塊化拆解XModule

上述是一個(gè)登錄模塊的例子,Module 作為基類,定義了模塊的一些生命周期方法。LoginModule是對外公開的業(yè)務(wù)接口,里面僅包含外部會用到的和登錄業(yè)務(wù)相關(guān)的方法。LoginModuleImplV1類是登錄邏輯的具體實(shí)現(xiàn),不對外公開,里面的私有成員變量和方法對外部是隱藏的,同時(shí)實(shí)現(xiàn)了Module和LoginModule的接口。Provider用于創(chuàng)建和管理Module實(shí)例。

這里采用的思路是,底層模塊和模塊之間,上層和底層之間只依賴接口頭文件,頭文件內(nèi)包含有限的需要對外暴露的接口。通過XModule這個(gè)框架,將實(shí)現(xiàn)和接口進(jìn)行分離。

為了將接口和實(shí)現(xiàn)分離,用到了 pimpl (Pointer to Implementation) 的理念,將對象的實(shí)現(xiàn)細(xì)節(jié)隱藏在指針背后。LoginModule接口負(fù)責(zé)定義對外公開的API,LoginModuleImplV1類負(fù)責(zé)定義LoginModule的具體實(shí)現(xiàn),也就是調(diào)用的指針實(shí)際指向的對象。調(diào)用方只能知道LoginModule中公開的API,而無法知道LoginModuleImplV1的實(shí)現(xiàn)細(xì)節(jié),可以降低調(diào)用方的使用門檻,也可以降低錯(cuò)誤使用的可能性。pimpl不僅解除了接口和實(shí)現(xiàn)之間的耦合關(guān)系,還可以降低文件間的編譯依賴關(guān)系,起到“編譯防火墻”的作用,可以提高一定的編譯效率。

// LoginModuleProvider 通過宏自動生成
X_MODULE_PROVIDER_DEFINE_SINGLE(LoginModule, MIN_VERSION, MAX_VERSION);
// LoginModuleImplV1Provider 通過宏自動生成
X_MODULE_DEFINE_SECONDARY_PROVIDER(LoginModuleImplV1, LoginModule);

XModule的模版開發(fā)方式,會增加很多類文件,為了方便,通過宏來控制Provider類的自動生成。其中MIN_VERSION和MAX_VERSION是該Module接口能支持的最小和最大的版本范圍,可以限制后期dll插件化加載時(shí),不加載在版本之外的dll,避免產(chǎn)生沖突和錯(cuò)誤,目前Provider的GetVersion使用的是MAX_VERSION。

// 由 X_MODULE_DEFINE_SECONDARY_PROVIDER 宏自動生成
class DLLEXPORT LoginModuleImplV1Provider : public LoginModuleProvider {
   public:
    LoginModule* Create() const {
      LoginModuleImplV1* p = new LoginModuleImplV1();
      ((Module*)p)->OnCreate();
      return p;
    } 
  };

LoginModuleImplV1Provider可以通過調(diào)用Create方法拿到對應(yīng)的LoginModuleImplV1實(shí)例。

x_module::ModuleCenter* module_center = x_module::ModuleCenter::GetInstance();
module_center->AcceptProviderType<LoginModuleProvider>();

ModuleCenter是所有Module的管理類,先通過x_module::ModuleCenter::GetInstance()拿到ModuleCenter的實(shí)例,它是一個(gè)跨dll的單例。然后要用之前的LoginModuleProvider去注冊一個(gè)Module類型到ModuleCenter中。LoginModuleProvider中定義了支持的Module類型,以及最小版本和最大版本,如果后續(xù)掃描到的dll中提供的對應(yīng)類型的Provider中GetVersion返回的值不在最大版本和最小版本之間,那么就不會被允許加載進(jìn)來。

module_center->AddProvider(new LoginModuleImplV1Provider());

通過這種方式,可以將LoginModuleImplV1Provider注冊到ModuleCenter中,然后創(chuàng)建并管理LoginModuleImplV1的實(shí)例。但是這樣就顯式地依賴了LoginModuleImplV1Provider,違反了前面說過的依賴倒置原則,對開閉原則也不友好,因?yàn)檫@樣就只能通過修改代碼來實(shí)現(xiàn)擴(kuò)展了。

#include <x_module/connector.h>
#include "login_module/login_module_impl.h"
X_MODULE_CONNECTOR
bool XModuleConnect(x_module::Owner& owner) {
    owner.add(new LoginModuleImplV1Provider());
    return true;
}

為了在加載dll時(shí),來注冊Provider,增加了一個(gè)connector.cc,添加一個(gè)XModuleConnect方法,讓dll被加載之后,能夠找到XModuleConnect這個(gè)符號方法,并進(jìn)行調(diào)用,在XModuleConnect被調(diào)用的時(shí)候,會調(diào)用AddProvider將Provider進(jìn)行注冊。

std::string path = GetProgramDir();
module_center->Install(path, "login_module");

由于目前l(fā)ogin_module.dll是直接放在exe同目錄的,所以這里直接獲取了一下exe絕對路徑,然后調(diào)用Install方法,將路徑和dll名login_module傳入進(jìn)去,這樣就完成了注冊。

auto* p_login_module = module_center->ModuleFromProtocol<LoginModule, LoginModuleProvider>();
if (p_login_module == nullptr) {
    (*move_result)->Error("-100", "login module 為空");
    return;
}
bool islogin = p_login_module->IsLogin();

在使用時(shí),只需要LoginModule和LoginModuleProvider這兩個(gè)抽象,就能獲取真實(shí)的LoginModuleImplV1這個(gè)實(shí)例,調(diào)用方僅需關(guān)心LoginModule所公開的API,完全屏蔽了對實(shí)現(xiàn)的依賴。后續(xù)底層擴(kuò)展成了LoginModuleImplV2,只要LoginModule的公開API不變,對上層是無感知的。這種方式完全遵循了前面提到的設(shè)計(jì)原則,對團(tuán)隊(duì)內(nèi)的多人維護(hù)以及后續(xù)的更新迭代都帶來了穩(wěn)定的保障。

基于vcpkg的C++依賴管理

模塊拆分之后,帶來的副作用就是依賴管理會變得更加復(fù)雜,到C++這邊就是CMakeLists的膨脹。從移動端的角度來看這個(gè)問題,Android可以通過Gradle來管理依賴,依賴庫構(gòu)建成aar之后上傳到Maven倉庫,implementation 'androidx.recyclerview:recyclerview:1.1.0'像這樣通過包名、庫名和版本號來依賴具體的庫。iOS有CocoaPods,通過添加pod 'AFNetworking', '~> 2.6'到Podfile來完成依賴的添加。前端也有NPM這樣的包管理器,所有依賴都在package.json這個(gè)文件中聲明和管理。Flutter側(cè)也可以通過pubspec來管理各個(gè)依賴庫。為了獲得一致的體驗(yàn),解決C++側(cè)依賴管理的痛點(diǎn),我們引入了微軟官方推出的vcpkg,vcpkg的清單模式可以得到類似的體驗(yàn)。

依賴庫配置

這里以fish-ffi-module模塊為例子,文件結(jié)構(gòu)如下,其中include文件里面是對外公開的頭文件,src文件包含當(dāng)前庫內(nèi)部使用的代碼,cmake文件下的config.cmake.in模版文件用于生成xxx-config.cmake的文件,用于被find_package找到。

.
├── CMakeLists.txt
├── LICENSE
├── cmake
│   └── config.cmake.in
├── include
│   └── fish_ffi_module.h
├── src
│   ├── connector.cc
│   ├── fish_ffi_module_impl_v1.cc
│   └── fish_ffi_module_impl_v1.h
├── vcpkg-configuration.json
└── vcpkg.json

vcpkg-configuration.json配置了私有源,后面會講到。vcpkg.json文件,聲明了當(dāng)前庫所依賴的其他庫,即vcpkg的依賴清單,其中"dependencies"字段聲明了所使用的依賴名稱。

{
	"name": "fish-ffi-module",
	"version": "1.0.0",
	"description": "A fish-ffi module based on fish-ffi-sdk.",
	"homepage": "",
  "dependencies": [
    "fish-ffi-sdk",
    "x-module",
    "flutter-sdk"
  ]
}

CMake工程最重要的就是CMakeLists文件了,里面配置了編譯相關(guān)的設(shè)置,添加了相關(guān)的注釋來幫助理解。

cmake_minimum_required(VERSION 3.15)
# 倉庫版本常量,升級時(shí)修改
set(FISH_FFI_MODULE_VERSION "1.0.0")
project(fish-ffi-module
    VERSION ${FISH_FFI_MODULE_VERSION}
    DESCRIPTION "A fish-ffi module based on fish-ffi-sdk."
		HOMEPAGE_URL ""
    LANGUAGES CXX)
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
# vcpkg清單中添加依賴之后,通過find_package就能找到
find_package(fish-ffi-sdk CONFIG REQUIRED)
find_package(flutter-sdk CONFIG REQUIRED)
find_package(x-module CONFIG REQUIRED)
# configure_package_config_file 生成config要用到
include(CMakePackageConfigHelpers)
# install 安裝要用到
include(GNUInstallDirs)
# 當(dāng)前庫的頭文件和源文件
aux_source_directory(include HEADER_LIST)
aux_source_directory(src SRC_LIST)
add_library(fish-ffi-module SHARED
    ${HEADER_LIST}
    ${SRC_LIST}
)
# 設(shè)置別名
add_library(fish-ffi-module::fish-ffi-module ALIAS fish-ffi-module)
# 設(shè)置動態(tài)庫導(dǎo)出宏,PRIVATE為編譯時(shí),INTERFACE為運(yùn)行時(shí)
if (BUILD_SHARED_LIBS AND WIN32)
    target_compile_definitions(fish-ffi-module
        PRIVATE "FISH_FFI_MODULE_EXPORT=__declspec(dllexport)"
        INTERFACE "FISH_FFI_MODULE_EXPORT=__declspec(dllimport)")
endif ()
target_compile_features(fish-ffi-module PUBLIC cxx_std_17)
# 添加頭文件
target_include_directories(fish-ffi-module PUBLIC 
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>
    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
# 鏈接庫文件
target_link_libraries(fish-ffi-module PRIVATE fish-ffi-sdk::fish-ffi-sdk)
target_link_libraries(fish-ffi-module PRIVATE flutter-sdk::flutter-sdk)
target_link_libraries(fish-ffi-module PRIVATE x-module::x-module)
# 基于config.cmake.in的模板生成xxx-config.cmake的文件
configure_package_config_file(
    cmake/config.cmake.in
    ${CMAKE_CURRENT_BINARY_DIR}/fish-ffi-module-config.cmake
    INSTALL_DESTINATION ${CMAKE_INSTALL_DATADIR}/fish-ffi-module
    NO_SET_AND_CHECK_MACRO)
# 生成xx-config-version.cmake文件
write_basic_package_version_file(
    ${CMAKE_CURRENT_BINARY_DIR}/fish-ffi-module-config-version.cmake
    VERSION ${FISH_FFI_MODULE_VERSION}
    COMPATIBILITY SameMajorVersion)
# 將上面生成的兩個(gè)config文件,安裝到share/fish-ffi-module下
install(
    FILES
        ${CMAKE_CURRENT_BINARY_DIR}/fish-ffi-module-config.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/fish-ffi-module-config-version.cmake
    DESTINATION
        ${CMAKE_INSTALL_DATADIR}/fish-ffi-module)
# 安裝頭文件
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
# install target
install(TARGETS fish-ffi-module
    EXPORT fish-ffi-module-targets
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
# 導(dǎo)出
install(EXPORT fish-ffi-module-targets
    NAMESPACE fish-ffi-module::
    DESTINATION ${CMAKE_INSTALL_DATADIR}/fish-ffi-module)

這里面最重要的一點(diǎn)是配置xx-config.cmake和xx-config-version.cmake的生成,vcpkg會在源碼首次拉下來的時(shí)候進(jìn)行編譯,編譯完在相應(yīng)庫的share目錄生成上述兩個(gè)文件,并且在CMake配置階段執(zhí)行,這樣在使用find_package的時(shí)候就能獲取到這個(gè)庫以及對應(yīng)版本號??偨Y(jié)一下就是,vcpkg幫助完成了代碼的下載、編譯和配置,然后就可以方便的鏈接三方庫了。

自定義私有源

私有源的自定義非常簡單,其實(shí)就是個(gè)Git倉庫,push到私有的git托管服務(wù)上即可。只需要將依賴庫的最新commit信息記錄到這個(gè)倉庫里面,通過模版化的配置就能完成依賴庫的發(fā)布。

.
├── ports
│		├── fish-ffi-module
│   │   ├── portfile.cmake
│   │   └── vcpkg.json
│   └── x-module
│       ├── portfile.cmake
│       └── vcpkg.json
├── versions
│   ├── f-
│		│		└── fish-ffi-module.json
│   └── x-
│		│		└── x-module.json
│   └──baseline.json
└── LICENSE

vcpkg里面對依賴庫的定義叫port,這里定義了兩個(gè)port,分別是fish-ffi-module和x-module。其中的文件說明如下:

  • portfile.cmake中定義了這個(gè)庫的git地址、分支、commitId、編譯配置等信息
  • vcpkg.json定義了這個(gè)port的依賴以及版本信息,如果有依賴,則會在編譯這個(gè)庫之前優(yōu)先編譯依賴。
  • versions下的文件按首字母分類,里面定義了version和git-tree的對應(yīng)關(guān)系。在port新增或更新之后,git-tree需要重新生成,通過git rev-parse HEAD:ports/x-module來生成git-tree,然后通過git commit --amend追加提交到剛剛的commit中。

在需要使用私有源的CMake工程根目錄,添加vcpkg-configuration.json,里面內(nèi)容如下。default-registry為默認(rèn)源,指向官方的地址即可。registries下添加自定義的私有源,再通過指定packages,表示里面的庫需要在這個(gè)私有源查找。這樣就完成了私有源的配置。

{
    "default-registry": {
      "kind": "git",
      "repository": "https://github.com/microsoft/vcpkg",
      "baseline": "f4b262b259145adb2ab0116a390b08642489d32b"
    },
    "registries": [
      {
        "kind": "git",
        "repository": "xxx.git",
        "baseline": "1ad54586a5a2fadb8c44d3f8f47754e849fc5a38",
        "packages": [ "x-module",  "fish-ffi-sdk", "fish-ffi-module"]
      }
    ]
  }

在versions文件夾下還有一個(gè)baseline.json的文件,這個(gè)文件主要是設(shè)置基線用的,不像其他的依賴管理工具,vcpkg主要是通過這個(gè)基線來設(shè)置當(dāng)前所使用的版本號的。

vcpkg可以勝任依賴管理的相關(guān)工作,綜上所述只是一個(gè)簡單使用,相比其他平臺的依賴管理工具略顯繁瑣,除此之外還有很多其他能力,需要到vcpkg.io的官方文檔里面探索了。

總結(jié)

Flutter應(yīng)用接入Windows平臺,主要遇到的問題就是Windows側(cè)的一些能力的提供,需要對齊Android和iOS的已有能力。因?yàn)槭褂玫氖荂++的開發(fā)語言,對于移動端開發(fā)者并不是那么友好,學(xué)習(xí)曲線相對會比較抖。不過一旦平臺側(cè)的能力完善之后,又可以回歸到Flutter這個(gè)熟悉的領(lǐng)域了,享受Flutter開發(fā)帶來的便捷。此外Windows應(yīng)用的開發(fā)不僅僅只是屏幕加大版的移動端開發(fā),還包括不同的輸入設(shè)備(鍵盤鼠標(biāo))、交互習(xí)慣、樣式風(fēng)格、操作系統(tǒng)特性等,為了更好的平臺體驗(yàn),會帶來一定的適配成本,這一塊后續(xù)也將持續(xù)投入。

以上就是Flutter應(yīng)用Windows平臺接入實(shí)踐詳解的詳細(xì)內(nèi)容,更多關(guān)于Flutter接入Windows平臺的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • VC實(shí)現(xiàn)Windows多顯示器編程的方法

    VC實(shí)現(xiàn)Windows多顯示器編程的方法

    這篇文章主要介紹了VC實(shí)現(xiàn)Windows多顯示器編程的方法,涉及VC獲取屏幕分辨率及顯示參數(shù)等技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • C++基于hook iat改變Messagebox實(shí)例

    C++基于hook iat改變Messagebox實(shí)例

    這篇文章主要介紹了C++基于hook iat改變Messagebox的方法,以實(shí)例形式展示了針對IAT(即導(dǎo)入地址表)以及hook的操作,有助于深入理解Windows程序設(shè)計(jì)原理,需要的朋友可以參考下
    2014-10-10
  • 詳細(xì)分析c++ const 指針與指向const的指針

    詳細(xì)分析c++ const 指針與指向const的指針

    這篇文章主要介紹了c++ const 指針與指向const的指針的相關(guān)資料,文中示例代碼非常詳細(xì),幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • c語言實(shí)現(xiàn)學(xué)生管理系統(tǒng)詳解

    c語言實(shí)現(xiàn)學(xué)生管理系統(tǒng)詳解

    這篇文章主要為大家介紹了c語言實(shí)現(xiàn)學(xué)生管理系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助<BR>
    2021-12-12
  • 賭你會懵的C語言指針進(jìn)階數(shù)組場景解析

    賭你會懵的C語言指針進(jìn)階數(shù)組場景解析

    這篇文章主要為大家介紹了關(guān)于C語言指針進(jìn)階的示例解析,來細(xì)化指針這一部分內(nèi)容,現(xiàn)在著重把一些指針的運(yùn)用情景搬出來康康,如果對指針盤的不是非常熟練,或者指針還出于入門階段的鐵子請繞道
    2022-02-02
  • 在std::thread中創(chuàng)建并管理QEventLoop的全面解析

    在std::thread中創(chuàng)建并管理QEventLoop的全面解析

    QEventLoop的工作原理可以簡單地理解為一個(gè)無限循環(huán),它會不斷地檢查是否有新的事件需要處理,如果有,就將事件從事件隊(duì)列中取出,然后找到相應(yīng)的事件處理器進(jìn)行處理,這篇文章主要介紹了在std::thread中創(chuàng)建并管理QEventLoop的全面指南,需要的朋友可以參考下
    2023-06-06
  • c語言strftime時(shí)間格式化示例

    c語言strftime時(shí)間格式化示例

    C/C++程序中需要程序顯示當(dāng)前時(shí)間,可以使用標(biāo)準(zhǔn)函數(shù)strftime,本文提供一個(gè)示例供大家參考
    2014-02-02
  • mfc入門教程之通過控制變量制作計(jì)算器

    mfc入門教程之通過控制變量制作計(jì)算器

    這篇文章主要介紹了mfc入門教程之通過控制變量制作計(jì)算器,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-04-04
  • C++中的內(nèi)存對齊實(shí)例詳解

    C++中的內(nèi)存對齊實(shí)例詳解

    這篇文章主要介紹了C++中的內(nèi)存對齊實(shí)例詳解的相關(guān)資料,這里不僅提供實(shí)現(xiàn)方法及代碼還提供了手工制作圖,來幫助到大家理解這部分知識,需要的朋友可以參考下
    2017-07-07
  • C語言main函數(shù)的參數(shù)及其返回值詳細(xì)解析

    C語言main函數(shù)的參數(shù)及其返回值詳細(xì)解析

    main函數(shù)的返回值用于說明程序的退出狀態(tài)。如果返回0,則代表程序正常退出;返回其它數(shù)字的含義則由系統(tǒng)決定。通常,返回非零代表程序異常退出
    2013-10-10

最新評論