以前也读了这个RGBD相机的一些源码但是发现自己的基本功是一点也不好,所以就搁置了很久,今天试图来回答一些问题。
说好的不会再出新品结果还是出了,估计这个市场还是可以的
自己就看一个例子里面的代码
就一个C文件,看的也简单一些
set(CMAKE_EXPORT_COMPILE_COMMANDS 1) add_executable(rs-color rs-color.c ../example.h) include_directories(../../common ../../third-party/imgui ../../C) target_link_libraries(rs-color ${DEPENDENCIES}) set_target_properties (rs-color PROPERTIES FOLDER "Examples/C" ) install(TARGETS rs-color RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
编译的文件都是使用Cmake来控制的,所以一开始写一些这个。
set(CMAKE_EXPORT_COMPILE_COMMANDS 1) 这个命令会让CMake在编译过程中输出 JSON 格式的编译命令到 compile_commands.json 文件中。这对于IDE的代码补全和静态分析很有帮助。
add_executable(rs-color rs-color.c ../example.h) 这个命令定义了一个rs-color的可执行目标,源代码文件是rs-color.c和example.h。
include_directories(../../common ../../third-party/imgui ../../C) 这个命令指定了包含路径,用于解析rs-color.c和example.h中的#include语句。
target_link_libraries(rs-color ${DEPENDENCIES}) 这个命令为rs-color目标指定了链接库,其中${DEPENDENCIES}是一个变量,包含所有依赖库的名字。
set_target_properties (rs-color PROPERTIES FOLDER "Examples/C" )这个命令为rs-color目标设置了一些属性,这里指定了在IDE的项目视图中,rs-color会出现在Examples/C文件夹下。
直接下来就看几个代码,是不是和学的C语言不太一样
这条语句rs2_error *e = 0;
1. 定义了一个指针e,指向rs2_error类型。
2. 将e初始化为0,也就是RS2_ERROR_NONE,表示没有错误。
rs2_context *ctx = rs2_create_context(RS2_API_VERSION, &e);
源码使用 Intel RealSense SDK 的 C API 创建了一个上下文对象 rs2_context,并将其地址赋给 ctx 变量。
同时,它传递了 RealSense SDK 的 API 版本号 RS2_API_VERSION 给 rs2_create_context() 函数,该函数将返回一个 rs2_context 对象。
在创建上下文对象时,还传递了一个错误处理器(error-handler)的地址 &e,以便在运行时捕获可能出现的错误。
如果发生someError,会通过*e = ...将e设置为相应的错误码。之后,在调用者可以检查*e的值来查看doSomething()是否发生错误。这是C语言中一个很常见的错误处理方式 - 通过指针传递错误码,如果有错误,被调用的函数会设置该指针为错误值。
调用者在调用后检查该值来进行错误处理。这种方式的好处是:
可以从函数返回额外的错误信息(除了函数返回值本身)。
不需要定义专门的错误返回类型,可以直接使用指向已有类型的指针。
简单和实用,适用于C语言的语法和习惯。
当然,这个方式也有一定的缺点,比如:
1. 如果不注意检查错误指针,难以发现错误,这会影响健壮性。
2. 错误指针需要与函数的正确返回值区分开来检查,有一定难度。
3. 错误信息只能通过指定的指针值返回,表达能力较有限。所以,对于rs2_error *e这样的指针,是可以直接作为C函数的参数进行传递的,这是C语言中一种简单实用的错误处理方式,但是也有一定的缺陷。
在这里被定义了很多
更具体的实现
1.析构函数~rs2_context(),在rs2_context被释放时会调用ctx->stop()。这是用于停止某个线程或后台服务。
2. 一个std::shared_ptr<:context>成员ctx。这是一个librealsense库中的context对象,通过shared_ptr智能指针进行管理。可以猜测,这个rs2_context结构体表示一个与librealsense的context相关的对象,它在释放时会停止该context,并通过shared_ptr管理context的生命周期。 其实这也是一个使用RAII(Resource Acquisition Is Initialization),通过在对象构造和析构时启动和停止资源,实现资源的自动管理。
rs2_context *ctx = rs2_create_context(RS2_API_VERSION, &e);
这段代码中,通过调用rs2_create_context()函数创建了一个rs2_context 实例,并将该实例的指针赋值给了 ctx 变量。这个 rs2_context 实例是在 rs2_create_context() 函数内部创建并初始化的,然后将其地址返回给调用者,调用者通过 ctx 变量来访问和操作该实例。
可以说rs2_context实例已经被初始化并设置好了,但不能直接说 rs2_context 里面是一个已经初始化过的结构体,因为 rs2_context 只是一个指针类型,并不存储任何数据。
结构体指针在 C 语言中被广泛使用,因为它可以方便地访问和操作结构体中的成员,而不需要对整个结构体进行复制。结构体指针可以通过指针运算和取值运算符来访问结构体成员,这使得对结构体的操作变得更加高效。
以下是一些常见的使用结构体指针的场景:
传递结构体指针作为函数参数:这种情况下,函数可以通过指针来访问和修改结构体的成员,从而避免了对整个结构体进行复制,提高了程序的效率。
动态内存分配:当需要动态创建一个结构体对象时,需要使用结构体指针来指向该对象。在动态分配内存时,使用结构体指针可以确保只分配所需的内存,并且可以方便地释放分配的内存。
链表和树等数据结构:链表和树等数据结构通常使用结构体指针来连接不同的节点,从而构建出完整的数据结构。
rs2_context *rs2_create_context(int api_version, rs2_error **error);
- api_version参数指定了librealsense API的版本号,用于向后兼容。
-e是个指针,如果有错误发生,会被设置为错误码。这是C语言常见的错误返回方式。
包含了以下字段:
message:错误消息,描述错误 details 的字符串。
function:发生错误的函数名。
args:发生错误的函数调用的参数。
exception_type:错误类型,很可能是一个enum,表示出错的原因。这个结构体通常用来表示异常信息,或是库函数调用后的错误详情。
c++ struct rs2_error { std::string message; // 错误消息 std::string function; // 函数名 std::string args; // 函数参数 rs2_exception_type exception_type; // 错误类型 };
如果一个函数返回一个结构体类型的值,那么需要使用一个结构体类型的变量来接收这个返回值。因为结构体类型通常比较大,如果直接将结构体类型的值作为函数的返回值返回,会导致复制整个结构体的内存空间,从而影响程序的性能。因此,C 语言中通常使用指向结构体的指针作为返回值,而不是直接返回结构体类型的值。
#include#include struct person { char name[50]; int age; }; struct person* create_person(const char* name, int age) { struct person* p = (struct person*) malloc(sizeof(struct person)); if (p != NULL) { strcpy(p->name, name); p->age = age; } return p; } int main() { struct person* p = create_person("John Doe", 30); if (p != NULL) { printf("Name: %s ", p->name); printf("Age: %d ", p->age); free(p); } return 0; }
完整代码
看这个
在上面的例子中,create_person() 函数返回一个指向:
struct person
结构体的指针。
该函数使用malloc()函数动态分配内存来存储结构体,然后将结构体的成员赋值为传入的参数。最后,该函数返回指向该结构体的指针。在 main() 函数中,调用 create_person() 函数来创建一个结构体实例,并打印出其成员的值。在使用完结构体后,还需要调用 free() 函数来释放动态分配的内存。
更具体的来分析:
struct person* p = (struct person*) malloc(sizeof(struct person));
调用malloc()函数,请求分配sizeof(struct person)字节的内存块。这将分配足够存放person结构体的内存。
malloc()返回 void *,所以我们需要强制类型转换为struct person*。这会将void *转换为person结构体的指针。
person *p将保存分配的内存块地址,我们可以通过p访问这个person对象。
分配的内存未初始化,需要手工初始化 person 对象的各个字段。
使用malloc()获取内存,强制类型转换为需要的指针类型,使用后释放内存。
https://www.intelrealsense.com/
https://github.com/IntelRealSense/librealsens
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !