三方库移植之NAPI开发[2]C/C++与JS的数据类型转

2024-05-16 01:52

本文主要是介绍三方库移植之NAPI开发[2]C/C++与JS的数据类型转,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通过NAPI框架进行C/C++与JS数据类型的转换

  • OpenHarmony NAPI将ECMAScript标准中定义的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八种数据类型,以及函数对应的Function类型,统一封装成napi_value类型,下文中表述为JS类型,用于接收ArkUI应用传递过来的数据及返回数据给ArkUI应用。

ECMAScript是一种由Ecma国际(通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,所以它可以理解为是JavaScript的一个标准,但实际上后两者是ECMA-262标准的实现和扩展。

  • 下面通过扩展一个简单的接口——Add(num1, num2)讲述具体细节,接口使用同步方式实现,NAPI的同步方式调用的扩展API代码处理流程如下图。

.cpp源码实现

  • 在《三方库移植之NAPI开发[1]—Hello OpenHarmony NAPI 》一文的基础上修改hellonapi.cpp文件,其余文件不变。
  • hellonapi.cpp内容如下:
#include <string.h>
#include "napi/native_node_api.h"
#include "napi/native_api.h"//NAPI定义API方法(接口业务实现)时的接收参数为(napi_env, napi_callback_info),
static napi_value Add(napi_env env, napi_callback_info info) {//获取2个参数,值的类型是js类型(napi_value)size_t requireArgc = 2;size_t argc = 2;napi_value args[2] = {nullptr};//NAPI提供了napi_get_cb_info()方法可从napi_callback_info中获取参数列表、this及其他数据NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));//获取并判断js参数类型napi_valuetype valuetype0;NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));napi_valuetype valuetype1;NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));if (valuetype0 != napi_number || valuetype1 != napi_number) {napi_throw_type_error(env, NULL, "Wrong arguments. 2 numbers are expected.");return NULL;}//将js类型(napi_value)的参数值转换成C++类型doubledouble value0;NAPI_CALL(env, napi_get_value_double(env, args[0], &value0));double value1;NAPI_CALL(env, napi_get_value_double(env, args[1], &value1));//将结果由C++类型(double)转换成js类型(napi_value)//NAPI提供了一些方法以便将C/C++不同类型的值转为node_value类型,返回给JS代码。napi_value sum;NAPI_CALL(env, napi_create_double(env, value0 + value1, &sum));//返回napi_value类型结果return sum;
}// napi_addon_register_func
//2.指定模块注册对外接口的处理函数,具体扩展的接口在该函数中声明
static napi_value registerFunc(napi_env env, napi_value exports)
{// 在napi_property_descriptor desc[]中将编写C的“Add方法与对外暴露Js的接口“add”方法进行关联static napi_property_descriptor desc[] = {{ "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;   
}// 1.先定义napi_module,指定当前NAPI模块对应的模块名
//以及模块注册对外接口的处理函数,具体扩展的接口在该函数中声明
// nm_modname: 模块名称,对应eTS代码为import nm_modname from '@ohos.ohos_shared_library_name'
//示例对应eTS代码为:import hellonapi from '@ohos.hellonapi'
static napi_module hellonapiModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = registerFunc, // 模块对外接口注册函数.nm_modname = "hellonapi",  // 自定义模块名.nm_priv = ((void*)0),.reserved = { 0 },
};//3.模块定义好后,调用NAPI提供的模块注册函数napi_module_register(napi_module* mod)函数注册到系统中。
// register module,设备启动时自动调用此constructor函数,把模块定义的模块注册到系统中
extern "C" __attribute__((constructor)) void hellonapiModuleRegister()
{napi_module_register(&hellonapiModule);
}

.cpp源码解析

注册NAPI模块、添加接口声明

// napi_addon_register_func
//2.指定模块注册对外接口的处理函数,具体扩展的接口在该函数中声明
static napi_value registerFunc(napi_env env, napi_value exports)
{static napi_property_descriptor desc[] = {{ "add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr }};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;   
}// 1.先定义napi_module,指定当前NAPI模块对应的模块名
//以及模块注册对外接口的处理函数,具体扩展的接口在该函数中声明
// nm_modname: 模块名称,对应eTS代码为import nm_modname from '@ohos.ohos_shared_library_name'
//示例对应eTS代码为:import hellonapi from '@ohos.hellonapi'
static napi_module hellonapiModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = registerFunc, // 模块对外接口注册函数.nm_modname = "hellonapi",  // 自定义模块名.nm_priv = ((void*)0),.reserved = { 0 },
};//3.模块定义好后,调用NAPI提供的模块注册函数napi_module_register(napi_module* mod)函数注册到系统中。
// register module,设备启动时自动调用此constructor函数,把模块定义的模块注册到系统中
extern "C" __attribute__((constructor)) void hellonapiModuleRegister()
{napi_module_register(&hellonapiModule);
}

接口业务实现C/C++代码

//NAPI定义API方法(接口业务实现)时的接收参数为(napi_env, napi_callback_info),
//其中napi_callback_info为上下文的信息
static napi_value Add(napi_env env, napi_callback_info info) {//获取2个参数,值的类型是js类型(napi_value)size_t requireArgc = 2;size_t argc = 2;napi_value args[2] = {nullptr};NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));//NAPI框架提供了napi_typeof方法用于获取指定js参数类型napi_valuetype valuetype0;NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));napi_valuetype valuetype1;NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));if (valuetype0 != napi_number || valuetype1 != napi_number) {napi_throw_type_error(env, NULL, "Wrong arguments. 2 numbers are expected.");return NULL;}//将js类型(napi_value)的参数值转换成C++类型doubledouble value0;NAPI_CALL(env, napi_get_value_double(env, args[0], &value0));double value1;NAPI_CALL(env, napi_get_value_double(env, args[1], &value1));//将结果由C++类型(double)转换成js类型(napi_value)napi_value sum;NAPI_CALL(env, napi_create_double(env, value0 + value1, &sum));//返回napi_value类型结果return sum;
}
获取参数
static napi_value Add(napi_env env, napi_callback_info info) {
......
}
  • NAPI定义API方法时的接收参数为(napi_env, napi_callback_info)

    • 其中napi_callback_info为上下文的信息。
  • NAPI提供了napi_get_cb_info()方法可从napi_callback_info中获取参数列表、this及其他数据。

napi_get_cb_info函数在ohos3.2beta3源码foundation/arkui/napi/native_engine/native_api.cpp中

// Methods to work with napi_callbacks
// Gets all callback info in a single call. (Ugly, but faster.)
NAPI_EXTERN napi_status napi_get_cb_info(napi_env env,              // [in] NAPI environment handlenapi_callback_info cbinfo, // [in] Opaque callback-info handlesize_t* argc,         // [in-out] Specifies the size of the provided argv array// and receives the actual count of args.napi_value* argv,     // [out] Array of valuesnapi_value* this_arg, // [out] Receives the JS 'this' arg for the callvoid** data)          // [out] Receives the data pointer for the callback.
{CHECK_ENV(env);CHECK_ARG(env, cbinfo);auto info = reinterpret_cast<NativeCallbackInfo*>(cbinfo);if ((argc != nullptr) && (argv != nullptr)) {size_t i = 0;for (i = 0; (i < *argc) && (i < info->argc); i++) {argv[i] = reinterpret_cast<napi_value>(info->argv[i]);}*argc = i;}if (argc != nullptr) {*argc = info->argc;}if (this_arg != nullptr) {*this_arg = reinterpret_cast<napi_value>(info->thisVar);}if (data != nullptr && info->functionInfo != nullptr) {*data = info->functionInfo->data;}return napi_clear_last_error(env);
}

napi_get_cb_info函数说明如下:

napi_status napi_get_cb_info(napi_env env,              napi_callback_info cbinfo, size_t* argc,                          napi_value* argv,     napi_value* this_arg, void** data)         
  • 参数说明:

    • [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可
    • [in] cbinfo: napi_callback_info对象,上下文的信息
    • [in-out] argc: argv数组的长度。若napi_callback_info中实际包含的参数的个数大于请求的数量argc,将只复制argc的值所指定数量的参数只argv中。若实际的参数个数小于请求的数量,将复制全部的参数,数组多余的空间用空值填充,并将参数实际长度写入argc。
    • [out] argv: 用于接收参数列表
    • [out] this_arg: 用于接收this对象
    • [out] data: NAPI的上下文数据 返回值:返回napi_ok表示转换成功,其他值失败。下面的返回napi_status方法一样。
  • 在Add方法中,调用napi_get_cb_info函数:

// env、info 参数由NAPI框架传入
static napi_value Add(napi_env env, napi_callback_info info) {
size_t requireArgc = 2;size_t argc = 2;napi_value args[2] = {nullptr};NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));napi_value sum;return sum;
}
JS类型值转换为C/C++类型的值
  • 此示例中传入的参数是Javascript值类型,被NAPI框架封装成统一的唯一类型——napi_value类型,为了能够进行计算,我们需要获取其对应在C/C++中的类型的值。
    • NAPI提供了包括以下方法以便获取不同类型的值(ohos3.2beta3源码foundation/arkui/napi/native_engine/native_api.cpp中)
      • napi_get_value_double
      • napi_get_value_int32
      • napi_get_value_uint32
      • napi_get_value_int64
      • napi_get_value_bool
      • napi_get_value_string_latin1(Copies LATIN-1 encoded bytes from a string into a buffer)
      • napi_get_value_string_utf8(Copies UTF-8 encoded bytes from a string into a buffer)
      • napi_get_value_string_utf16
      • napi_get_value_external
      • napi_get_value_bigint_int64
      • napi_get_value_bigint_uint64
      • napi_get_value_bigint_words
    • 此示例hellonapi.cpp中使用到了napi_get_value_double方法,函数定义如下:

NAPI_EXTERN napi_status napi_get_value_double(napi_env env, napi_value value, double* result)
{CHECK_ENV(env);CHECK_ARG(env, value);CHECK_ARG(env, result);auto nativeValue = reinterpret_cast<NativeValue*>(value);RETURN_STATUS_IF_FALSE(env, nativeValue->TypeOf() == NATIVE_NUMBER, napi_number_expected);*result = *reinterpret_cast<NativeNumber*>(nativeValue->GetInterface(NativeNumber::INTERFACE_ID));return napi_clear_last_error(env);
}

参数说明:

  • [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可。
  • [in] value: 传入要转换的napi_value类型数据对象(可视为一个JS对象)。
  • [out] result: 转换出对应类型(double)结果。 返回值:返回napi_ok表示转换成功,其他值失败。

获取参数的C/C++类型的值前,需要先判断值的类型,本示例需要判断传入参数的JS值必须为number类型

  • NAPI框架提供了napi_typeof方法用于获取指定对象的类型,其函数定义如下:
// Methods to get the native napi_value from Primitive type
NAPI_EXTERN napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
{CHECK_ENV(env);CHECK_ARG(env, value);CHECK_ARG(env, result);auto nativeValue = reinterpret_cast<NativeValue*>(value);*result = (napi_valuetype)nativeValue->TypeOf();return napi_clear_last_error(env);
}

参数说明:

  • [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可。
  • [in] value: 传入要转换的napi_value类型数据对象(可视为一个JS对象)。
  • [out] result: 返回value参数对应的JS类型。
    • napi_valuetype对应了ECMAScript标准中定义的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八种数据类型,以及函数对应的Function类型。
    • 另外,napi_valuetype还包括了一个napi_external类型,其表示没有任何属性也没有任何原型的对象。

综上所述参数类型判断及值转换,示例代码如下:

static napi_value Add(napi_env env, napi_callback_info info) {// 1\. 获取2个参数,值的类型是js类型(napi_value)size_t requireArgc = 2;size_t argc = 2;napi_value args[2] = {nullptr};NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));// 2\. 获取并判断js参数类型napi_valuetype valuetype0;NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));napi_valuetype valuetype1;NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));//输入的数据类型异常处理if (valuetype0 != napi_number || valuetype1 != napi_number) {napi_throw_type_error(env, NULL, "Wrong arguments. 2 numbers are expected.");return NULL;}// 3\. 将js类型(napi_value)的参数值转换成C++类型doubledouble value0;NAPI_CALL(env, napi_get_value_double(env, args[0], &value0));double value1;NAPI_CALL(env, napi_get_value_double(env, args[1], &value1));napi_value sum;return sum;
计算结果转换为JS类型并返回
static napi_value Add(napi_env env, napi_callback_info info) {
···// 4\. 将结果由C++类型(double)转换成js类型(napi_value)napi_value sum;NAPI_CALL(env, napi_create_double(env, value0 + value1, &sum));
··· 
}
  • 计算的结果是C/C++类型,需要转换成NAPI node_value类型返回给JS。

  • NAPI提供了一些方法以便将C/C++不同类型的值转为node_value类型,返回给JS代码。例如:

    • napi_create_double
    • napi_create_int32
    • napi_create_uint32
    • napi_create_int64
    • napi_create_string_latin1
    • napi_create_string_utf8
    • napi_create_string_utf16
  • 以napi_create_double方法为例,函数定义如下:

NAPI_EXTERN napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
{CHECK_ENV(env);CHECK_ARG(env, result);auto engine = reinterpret_cast<NativeEngine*>(env);auto resultValue = engine->CreateNumber(value);*result = reinterpret_cast<napi_value>(resultValue);return napi_clear_last_error(env);
}

参数说明:
[in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可.
[in] value: 传入要转换的double类型数据值.
[out] result: 转换出结果

ArkUI应用实现代码

ArkUI应用实现目录结构

index.ets内容如下:

index.ets

import hellonapi from '@ohos.hellonapi'@Entry
@Component
export struct HelloNAPI {private textInputController1: TextInputController = new TextInputController()private textInputController2: TextInputController = new TextInputController()private tittle: string = 'C/C++与JS的数据类型转换'private message: string = '计算x+y'private tipsNum1: string = '请输入X:'private tipsNum2: string = '请输入Y:'private tipsResult: string = '结果:'private buttonSubmit: string = '计算'@State result: number = 0.0@State num1: number = 0.0@State num2: number = 0.0build() {Row() {Column() {Row(){Text(this.tittle).height('100%').align(Alignment.Center).fontSize(50).fontWeight(800)}.height('30%').width('100%').justifyContent(FlexAlign.Center)Row(){Text(this.message).height('100%').align(Alignment.Center).fontSize(35).fontWeight(500)}.height('15%').width('100%').justifyContent(FlexAlign.Center)Row(){Text(this.tipsNum1).fontColor(Color.Black).fontSize('65px').width('30%').height('100%').margin({left:30})TextInput({ placeholder: 'X', controller:this.textInputController1}).type(InputType.Number).height('100%').width('60%').margin({left:10,right:30}).fontSize('25px').onChange(value =>{this.num1 = parseFloat(value)})}.height('6%').width('100%').justifyContent(FlexAlign.Start)Row(){Text(this.tipsNum2).fontColor(Color.Black).fontSize('65px').width('30%').height('100%').margin({left:30})TextInput({ placeholder: 'Y', controller:this.textInputController2}).type(InputType.Number).height('100%').width('60%').margin({left:10,right:30}).fontSize('25px').onChange(value =>{this.num2 = parseFloat(value)})}.height('6%').width('100%').margin({top:20})Row(){Text(this.tipsResult).fontColor(Color.Black).fontSize(35).width('40%').height('100%').margin({left:30})Text(''+this.result).fontColor(Color.Black).fontSize(35).width('60%').height('100%')}.height('10%').width('100%').touchable(false)Row(){Button(this.buttonSubmit).fontSize(37).fontWeight(FontWeight.Bold).margin({top:5}).height(80).width(200).onClick(() => {//hellonapi为BUILD.gn文件中定义的ohos_shared_library结构体名称this.result = hellonapi.add(this.num1,this.num2)})}.height('30%').width('100%').justifyContent(FlexAlign.Center)}.width('100%')}.height('100%')}
}

效果图如下:

index.ets解析

  • 参数说明
字段类型说明
tittlestring标题
messagestring说明
tipsNum1number提示输入第一个参数
tipsNum2number提示输入第二个参数
tipsResultstring提示结果
buttonSubmitstring计算按钮名称
resultstring结果
num1number输入的第一个数
num2number输入的第二个数
  • 设置参数
import hellonapi from '@ohos.hellonapi'@Entry
@Component
export struct HelloNAPI {private textInputController1: TextInputController = new TextInputController()private textInputController2: TextInputController = new TextInputController()private tittle: string = 'C/C++与JS的数据类型转换'private message: string = '计算x+y'private tipsNum1: string = '请输入X:'private tipsNum2: string = '请输入Y:'private tipsResult: string = '结果:'private buttonSubmit: string = '计算'@State result: number = 0.0@State num1: number = 0.0@State num2: number = 0.0...build() {...}
}
  • 界面实现
import hellonapi from '@ohos.hellonapi'@Entry
@Component
export struct HelloNAPI {...build() {Row() {Column() {Row(){Text(this.tittle).height('100%').align(Alignment.Center).fontSize(50).fontWeight(800)}.height('30%').width('100%').justifyContent(FlexAlign.Center)Row(){Text(this.message).height('100%').align(Alignment.Center).fontSize(35).fontWeight(500)}.height('15%').width('100%').justifyContent(FlexAlign.Center)Row(){Text(this.tipsNum1).fontColor(Color.Black).fontSize('65px').width('30%').height('100%').margin({left:30})TextInput({ placeholder: 'X', controller:this.textInputController1}).type(InputType.Number).height('100%').width('60%').margin({left:10,right:30}).fontSize('25px').onChange(value =>{this.num1 = parseFloat(value)})}.height('6%').width('100%').justifyContent(FlexAlign.Start)Row(){Text(this.tipsNum2).fontColor(Color.Black).fontSize('65px').width('30%').height('100%').margin({left:30})TextInput({ placeholder: 'Y', controller:this.textInputController2}).type(InputType.Number).height('100%').width('60%').margin({left:10,right:30}).fontSize('25px').onChange(value =>{this.num2 = parseFloat(value)})}.height('6%').width('100%').margin({top:20})Row(){Text(this.tipsResult).fontColor(Color.Black).fontSize(35).width('40%').height('100%').margin({left:30})Text(''+this.result).fontColor(Color.Black).fontSize(35).width('60%').height('100%')}.height('10%').width('100%').touchable(false)Row(){Button(this.buttonSubmit).fontSize(37).fontWeight(FontWeight.Bold).margin({top:5}).height(80).width(200).onClick(() => {//hellonapi为BUILD.gn文件中定义的ohos_shared_library结构体名称this.result = hellonapi.add(this.num1,this.num2)})}.height('30%').width('100%').justifyContent(FlexAlign.Center)}.width('100%')}.height('100%')}
}
  • 绑定事件、关联参数
    两个TextInput组件分别绑定onChange事件,并分别关联num1,num2来记录输入的参数
        Row(){Text(this.tipsNum1).fontColor(Color.Black).fontSize('65px').width('30%').height('100%').margin({left:30})TextInput({ placeholder: 'X', controller:this.textInputController1}).type(InputType.Number).height('100%').width('60%').margin({left:10,right:30}).fontSize('25px').onChange(value =>{this.num1 = parseFloat(value)})}.height('6%').width('100%').justifyContent(FlexAlign.Start)Row(){Text(this.tipsNum2).fontColor(Color.Black).fontSize('65px').width('30%').height('100%').margin({left:30})TextInput({ placeholder: 'Y', controller:this.textInputController2}).type(InputType.Number).height('100%').width('60%').margin({left:10,right:30}).fontSize('25px').onChange(value =>{this.num2 = parseFloat(value)})}.height('6%').width('100%').margin({top:20})
  • Button组件添加点击事件,调用hellonapiu.cpp中的Add方法(调用js中的add,add和Add已经在napi.cpp中绑定)
Row(){Button(this.buttonSubmit).fontSize(37).fontWeight(FontWeight.Bold).margin({top:5}).height(80).width(200).onClick(() => {//hellonapi为BUILD.gn文件中定义的ohos_shared_library结构体名称this.result = hellonapi.add(this.num1,this.num2)})
  • 通过NAPI框架输入到C的Add函数的JS参数是num1和num2,输出的JS参数是result

@ohos.hellonapi.d.ts接口文档

declare namespace hellonapi {export const add: (a: number, b: number) => number;/*** ** @since 9* @syscap SystemCapability.Ability.AbilityRuntime.AbilityCore*/}
export default hellonapi;

总结

hellonapi.cpp

index.ets

为了帮助到大家能够更有效的学习OpenHarmony 开发的内容,下面特别准备了一些相关的参考学习资料:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

这篇关于三方库移植之NAPI开发[2]C/C++与JS的数据类型转的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/993544

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

C++的模板(八):子系统

平常所见的大部分模板代码,模板所传的参数类型,到了模板里面,或实例化为对象,或嵌入模板内部结构中,或在模板内又派生了子类。不管怎样,最终他们在模板内,直接或间接,都实例化成对象了。 但这不是唯一的用法。试想一下。如果在模板内限制调用参数类型的构造函数会发生什么?参数类的对象在模板内无法构造。他们只能从模板的成员函数传入。模板不保存这些对象或者只保存他们的指针。因为构造函数被分离,这些指针在模板外

C++工程编译链接错误汇总VisualStudio

目录 一些小的知识点 make工具 可以使用windows下的事件查看器崩溃的地方 dumpbin工具查看dll是32位还是64位的 _MSC_VER .cc 和.cpp 【VC++目录中的包含目录】 vs 【C/C++常规中的附加包含目录】——头文件所在目录如何怎么添加,添加了以后搜索头文件就会到这些个路径下搜索了 include<> 和 include"" WinMain 和

C/C++的编译和链接过程

目录 从源文件生成可执行文件(书中第2章) 1.Preprocessing预处理——预处理器cpp 2.Compilation编译——编译器cll ps:vs中优化选项设置 3.Assembly汇编——汇编器as ps:vs中汇编输出文件设置 4.Linking链接——链接器ld 符号 模块,库 链接过程——链接器 链接过程 1.简单链接的例子 2.链接过程 3.地址和

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型

C++入门01

1、.h和.cpp 源文件 (.cpp)源文件是C++程序的实际实现代码文件,其中包含了具体的函数和类的定义、实现以及其他相关的代码。主要特点如下:实现代码: 源文件中包含了函数、类的具体实现代码,用于实现程序的功能。编译单元: 源文件通常是一个编译单元,即单独编译的基本单位。每个源文件都会经过编译器的处理,生成对应的目标文件。包含头文件: 源文件可以通过#include指令引入头文件,以使

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

js+css二级导航

效果 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Con

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa