鱼香ROS社区
    • 版块
    • 最新
    • 未解决
    • 已解决
    • 群组
    • 注册
    • 登录
    紧急通知:禁止一切关于政治&VPN翻墙等话题,发现相关帖子会立马删除封号
    提问前必看的发帖注意事项: 社区问答规则(小鱼个人)更新 | 高质量帖子发布指南

    C语言如何实现对其他函数的跨文件调用

    已定时 已固定 已锁定 已移动
    机器人学
    函数 跨文件
    2
    18
    925
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 2
      2251752108 @2251752108
      最后由 编辑

      @2251752108 在 C语言如何实现对其他函数的跨文件调用 中说:

      @小伊 在cmakelists中add_subdirectory(Sample-PointCloud)是什么意思

      @小伊 target_link_libraries(point_cloud OrbbecSDK ${OpenCV_LIBS})这句表示什么

      1 条回复 最后回复 回复 引用 0
      • 小伊小
        机器人小伊
        最后由 编辑

        在C语言(以及C++等语言)项目中,使用CMake作为构建系统可以帮助管理项目的编译、链接等构建过程。这里提到的CMakeLists.txt文件是CMake的配置文件,它定义了如何构建项目。针对您的问题,我将逐一解释提到的两条CMake命令的含义。

        1. add_subdirectory(Sample-PointCloud)

        add_subdirectory命令用于在当前目录(即当前正在处理的CMakeLists.txt文件所在的目录)下添加一个新的子目录,并对该子目录执行CMake构建过程。这里,Sample-PointCloud是一个目录名,意味着CMake将会在当前项目的根目录(或相对于当前CMakeLists.txt文件的位置)下查找名为Sample-PointCloud的目录,并在该目录下查找另一个CMakeLists.txt文件来构建该子项目。

        这种机制常用于大型项目,其中可能包含多个库或应用程序,每个部分都可以有自己的构建配置。使用add_subdirectory可以方便地组织和管理这些部分。

        2. target_link_libraries(point_cloud OrbbecSDK ${OpenCV_LIBS})

        target_link_libraries命令用于指定一个或多个目标(如可执行文件或库)在链接阶段需要链接的库。在这个例子中:

        • point_cloud 是目标名,它可能是一个之前通过add_executable或add_library命令定义的可执行文件或库。
        • OrbbecSDK 是需要链接到point_cloud目标的库名。这意味着在构建point_cloud时,链接器会查找名为OrbbecSDK的库文件(可能是libOrbbecSDK.a、libOrbbecSDK.so等,取决于操作系统和构建类型)。
        • ${OpenCV_LIBS} 是一个变量,它应该在项目的其他地方(可能是通过find_package命令)被设置为OpenCV库的一个或多个文件列表。这意味着point_cloud目标还会链接OpenCV库。

        总结来说,这条命令的作用是指示CMake在构建point_cloud目标时,将其与OrbbecSDK库和OpenCV库链接起来。这对于使用这些库提供的功能(如处理点云数据或图像处理)是必要的。

        这两个命令在CMake构建系统中非常常见,它们帮助组织和管理大型项目,以及确保项目正确链接到所需的依赖库。


        以上为生成回答,仅供参考~

        我是小伊,已接入ChatGpt,所有回复,仅供参考~

        1 条回复 最后回复 回复 引用 0
        • 2
          2251752108
          最后由 编辑

          @小伊 如何在cmakelists文件中体现依赖关系

          1 条回复 最后回复 回复 引用 0
          • 小伊小
            机器人小伊
            最后由 编辑

            在CMakeLists.txt文件中,你可以通过多种方式来表示和管理项目中的依赖关系。以下是一些常见的方法:

            1. 添加子目录(Subdirectories)

            如果你的项目包含多个子目录,每个子目录本身也是一个CMake项目,你可以使用add_subdirectory命令来包含这些子目录。这样,子目录中的目标(targets)会被添加到主项目中,并且可以相互依赖。

            # CMakeLists.txt (根目录)
            cmake_minimum_required(VERSION 3.10)
            project(MyProject)
            
            # 添加子目录
            add_subdirectory(library)
            add_subdirectory(app)
            
            # CMakeLists.txt (library 目录)
            add_library(mylib SHARED mylib.cpp)
            
            # CMakeLists.txt (app 目录)
            add_executable(myapp main.cpp)
            target_link_libraries(myapp PRIVATE mylib)
            

            在这个例子中,app目录中的可执行文件myapp依赖于library目录中的库mylib。

            2. 使用target_link_libraries

            如果你已经定义了目标(如库或可执行文件),并且一个目标依赖于另一个目标,你可以使用target_link_libraries来指定依赖关系。

            # CMakeLists.txt
            cmake_minimum_required(VERSION 3.10)
            project(MyProject)
            
            # 添加库
            add_library(mylib SHARED mylib.cpp)
            
            # 添加可执行文件并链接库
            add_executable(myapp main.cpp)
            target_link_libraries(myapp PRIVATE mylib)
            

            3. 使用target_include_directories和target_compile_definitions

            如果你的依赖关系不仅仅是链接库,还包括头文件路径或预处理器定义,你可以使用target_include_directories和target_compile_definitions来指定这些依赖关系。

            # CMakeLists.txt
            cmake_minimum_required(VERSION 3.10)
            project(MyProject)
            
            # 添加库
            add_library(mylib SHARED mylib.cpp)
            target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
            
            # 添加可执行文件并链接库
            add_executable(myapp main.cpp)
            target_link_libraries(myapp PRIVATE mylib)
            target_include_directories(myapp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
            

            4. 使用find_package和target_link_libraries(针对外部库)

            如果你的项目依赖于外部库(如Boost、OpenCV等),你可以使用find_package来查找这些库,并使用target_link_libraries来链接它们。

            # CMakeLists.txt
            cmake_minimum_required(VERSION 3.10)
            project(MyProject)
            
            # 查找外部库
            find_package(Boost REQUIRED)
            
            # 添加可执行文件并链接Boost库
            add_executable(myapp main.cpp)
            target_link_libraries(myapp PRIVATE Boost::system)
            

            5. 使用interface_include_directories和interface_compile_definitions(CMake 3.11+)

            对于更精细的控制,CMake 3.11及更高版本引入了interface_include_directories和interface_compile_definitions,它们允许你分别指定接口级和使用级(即私有)的包含目录和编译定义。

            # CMakeLists.txt (CMake 3.11+)
            cmake_minimum_required(VERSION 3.11)
            project(MyProject)
            
            # 添加库
            add_library(mylib SHARED mylib.cpp)
            target_include_directories(mylib
                INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
                PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
            )
            

            通过这些方法,你可以在CMakeLists.txt文件中清晰地表示和管理项目中的依赖关系。


            以上为生成回答,仅供参考~

            我是小伊,已接入ChatGpt,所有回复,仅供参考~

            2 1 条回复 最后回复 回复 引用 0
            • 2
              2251752108 @小伊
              最后由 编辑

              @小伊 在 C语言如何实现对其他函数的跨文件调用 中说:

              如果你的依赖关系不仅仅是链接库,还包括头文件路径或预处理器定义,你可以使用target_include_directories和target_compile_definitions来指定这些依赖关系。

              @小伊 这一点能不能再仔细说一下

              1 条回复 最后回复 回复 引用 0
              • 小伊小
                机器人小伊
                最后由 编辑

                当然可以。在C语言项目中,特别是使用现代构建系统(如CMake)时,管理跨文件调用函数(即跨多个源文件的项目)不仅仅是关于链接库文件(.lib, .a, .so等),还涉及到头文件路径的管理和预处理器定义。这些设置有助于编译器找到必要的头文件和正确解析代码中的宏定义。

                target_include_directories

                target_include_directories 是 CMake 中用于指定目标(target)的头文件搜索路径的命令。这有助于编译器在编译过程中找到包含的文件(即#include指令引用的文件)。

                示例

                假设你的项目结构如下:

                project/
                ├── CMakeLists.txt
                ├── src/
                │   ├── main.c
                │   └── foo.c
                └── include/
                    └── foo.h
                

                在这个例子中,main.c 需要包含 foo.h。你可以在 CMakeLists.txt 中这样设置:

                cmake_minimum_required(VERSION 3.10)
                project(MyProject)
                
                # 添加源文件
                set(SOURCES src/main.c src/foo.c)
                
                # 创建可执行文件
                add_executable(MyExecutable ${SOURCES})
                
                # 指定头文件目录
                target_include_directories(MyExecutable PRIVATE include)
                

                这里的 target_include_directories 命令告诉 CMake 在编译 MyExecutable 时,应该在 include 目录下查找头文件。

                target_compile_definitions

                target_compile_definitions 是 CMake 中用于为目标添加预处理器定义的命令。这可以用于定义宏,这些宏可以在代码中通过 #ifdef, #ifndef, #if, #else, #elif, 和 #endif 指令进行检查和使用。

                示例

                假设你有一个宏 DEBUG_MODE,你希望在编译时根据这个宏来决定是否启用调试代码:

                // foo.c
                #ifdef DEBUG_MODE
                    printf("Debug mode is enabled.\n");
                #endif
                

                你可以在 CMakeLists.txt 中这样设置:

                cmake_minimum_required(VERSION 3.10)
                project(MyProject)
                
                # 添加源文件
                set(SOURCES src/main.c src/foo.c)
                
                # 创建可执行文件
                add_executable(MyExecutable ${SOURCES})
                
                # 添加预处理器定义
                target_compile_definitions(MyExecutable PRIVATE DEBUG_MODE)
                

                在这个例子中,target_compile_definitions 命令告诉 CMake 在编译 MyExecutable 时,应该定义 DEBUG_MODE 宏。这意味着 foo.c 中的调试代码会被启用。

                总结

                • target_include_directories 用于指定编译器在编译目标时应该查找头文件的目录。
                • target_compile_definitions 用于为目标添加预处理器定义,这些定义可以在代码中使用条件编译指令进行检查。

                这两个命令对于管理跨文件依赖和确保代码在不同编译环境下正确编译非常有用。


                以上为生成回答,仅供参考~

                我是小伊,已接入ChatGpt,所有回复,仅供参考~

                1 条回复 最后回复 回复 引用 0
                • 2
                  2251752108
                  最后由 编辑

                  @小伊
                  /usr/bin/ld: CMakeFiles/main.dir/main.c.o: in function main': main.c:(.text+0x18): undefined reference to color_viewer'
                  collect2: error: ld returned 1 exit status
                  make[2]: *** [c/Main_Test/CMakeFiles/main.dir/build.make:97:bin/main] 错误 1
                  make[1]: *** [CMakeFiles/Makefile2:1168:c/Main_Test/CMakeFiles/main.dir/all] 错误 2
                  make: *** [Makefile:91:all] 错误 2

                  1 条回复 最后回复 回复 引用 0
                  • 小伊小
                    机器人小伊
                    最后由 编辑

                    这个错误信息表明在链接阶段,链接器(ld)无法找到名为 color_viewer 的函数的定义。这通常意味着以下几种可能的情况:

                    1. 未定义函数:在你的代码中可能调用了 color_viewer 函数,但是在你的项目或链接的库中并没有这个函数的实现。检查是否有遗漏的源文件或者库没有正确链接。

                    2. 链接库问题:如果 color_viewer 函数定义在外部库中,确保这个库已经被正确添加到你的项目中,并且在链接时被包含进来。在 CMake 中,你需要使用 target_link_libraries 命令来链接这个库。

                    3. 声明与定义不匹配:如果 color_viewer 函数是在另一个文件中定义的,确保它的声明(在头文件中)和定义(在源文件中)完全一致,包括返回类型、函数名和参数列表。

                    4. 编译单元问题:确保包含 color_viewer 函数定义的源文件被正确编译并参与到链接过程中。

                    解决步骤

                    1. 检查 color_viewer 函数的定义:

                      • 查找 color_viewer 函数的定义,确认它存在于你的项目中或者某个被链接的库中。
                      • 如果它是外部库的一部分,确保你已经正确安装了该库,并且 CMakeLists.txt 文件中已经添加了相应的 find_package 和 target_link_libraries 命令。
                    2. 检查 CMakeLists.txt:

                      • 确保所有相关的源文件都被添加到 add_executable 或 add_library 命令中。
                      • 如果使用了外部库,检查是否有类似以下的命令:
                        find_package(SomeLibrary REQUIRED)
                        target_link_libraries(your_target_name SomeLibrary)
                        
                    3. 重新生成项目:

                      • 在修改了 CMakeLists.txt 后,不要忘记重新运行 CMake 以生成新的 Makefile,例如:
                        cmake ..
                        make clean  # 清理旧的构建文件(可选)
                        make
                        
                    4. 检查编译器和链接器输出:

                      • 仔细查看编译器和链接器的输出信息,看是否有其他相关的错误或警告。

                    通过以上步骤,你应该能够定位并解决链接错误。如果问题仍然存在,可能需要更详细地检查你的项目配置或寻求更具体的帮助。


                    以上为生成回答,仅供参考~

                    我是小伊,已接入ChatGpt,所有回复,仅供参考~

                    1 条回复 最后回复 回复 引用 0
                    • 2
                      2251752108
                      最后由 编辑

                      @小伊 zztg@zztg:~/桌面/file_test/build$ cmake ..
                      CMake Error at CMakeLists.txt:7:
                      Parse error. Expected a command name, got unquoted argument with text
                      "find_package(Sample-ColorViewer".

                      1 条回复 最后回复 回复 引用 0
                      • 小伊小
                        机器人小伊
                        最后由 编辑

                        这个错误提示表明在 CMakeLists.txt 文件的第7行存在语法错误。错误的具体内容是 find_package(Sample-ColorViewer",这里有几个问题:

                        1. 命令名称错误:正确的命令是 find_package,但通常这个命令是用来查找和包含CMake模块或第三方库的,而更常用的命令是 find_package 的变体 find_package(RequiredPackageName [version] [EXACT] [REQUIRED] [COMPONENTS components...]),但这里似乎意图是 find_package 的一个误用或者拼写错误,正确的可能是 find_package(某些库)。不过,更常见的是 find_package 用于查找如 Boost, OpenCV 等库,并且命令名应该是 find_package(注意没有 "d")。

                        2. 括号使用错误:在错误信息中,使用的是全角括号“(”和“)”,而不是半角括号“(”和)`。在 CMakeLists.txt 中应使用半角括号。

                        3. 包名可能错误:Sample-ColorViewer 看起来像是项目名或某个特定的包名,但通常 find_package 用于查找已安装的库,而不是项目名。如果 Sample-ColorViewer 是一个库,确保它已正确安装,并且 CMakeLists.txt 中的命令格式正确。

                        解决这个问题的步骤如下:

                        1. 检查并修正命令名:确认你是否想要使用 find_package(通常用于查找库),或者是其他命令。如果是查找库,确保库名和版本(如果指定)正确。

                        2. 使用正确的括号:将全角括号“(”和“)”替换为半角括号“(”和)`。

                        3. 检查包名:如果 Sample-ColorViewer 是一个库,确保它已安装,并且 CMake 可以找到它。如果它是你的项目名,你可能不需要使用 find_package。

                        4. 重新运行 CMake:修改完 CMakeLists.txt 后,重新运行 CMake 以查看是否还有其他错误。

                        如果 Sample-ColorViewer 是你的项目或模块名,并且你想在 CMake 中包含它,你可能需要使用 add_subdirectory() 命令来添加包含它的目录,而不是使用 find_package()。


                        以上为生成回答,仅供参考~

                        我是小伊,已接入ChatGpt,所有回复,仅供参考~

                        2 1 条回复 最后回复 回复 引用 0
                        • 2
                          2251752108 @小伊
                          最后由 编辑

                          @小伊 在 C语言如何实现对其他函数的跨文件调用 中说:

                          如果 Sample-ColorViewer 是你的项目或模块名,并且你想在 CMake 中包含它,你可能需要使用 add_subdirectory() 命令来添加包含它的目录,

                          @小伊 这里如何编写

                          1 条回复 最后回复 回复 引用 0
                          • 小伊小
                            机器人小伊
                            最后由 编辑

                            在 CMake 中使用 add_subdirectory() 命令来添加和构建子目录(或模块)是一种常见的做法。假设你的项目结构如下:

                            /MyProject
                                /CMakeLists.txt
                                /Sample-ColorViewer
                                    /CMakeLists.txt
                                    /src
                                        /main.c
                                        /other_function.c
                                    /include
                                        /sample_color_viewer.h
                            

                            在这个例子中,MyProject 是你的主项目目录,而 Sample-ColorViewer 是一个子模块或子目录,它包含自己的 CMakeLists.txt 文件和一些源代码文件。

                            主项目 CMakeLists.txt

                            在主项目的 CMakeLists.txt 文件中,你需要使用 add_subdirectory() 命令来包含并构建 Sample-ColorViewer 子目录。下面是一个示例:

                            cmake_minimum_required(VERSION 3.10)
                            project(MyProject)
                            
                            # 添加 Sample-ColorViewer 子目录
                            add_subdirectory(Sample-ColorViewer)
                            
                            # 如果你在主项目中还有其他目标,可以在这里添加
                            # add_executable(MyExecutable main.c)
                            # target_link_libraries(MyExecutable PRIVATE SampleColorViewer)
                            

                            Sample-ColorViewer 目录的 CMakeLists.txt

                            在 Sample-ColorViewer 子目录中,你需要一个 CMakeLists.txt 文件来定义如何构建这个模块。以下是一个简单的示例:

                            cmake_minimum_required(VERSION 3.10)
                            project(SampleColorViewer)
                            
                            # 指定 C 标准(可选)
                            set(CMAKE_C_STANDARD 11)
                            set(CMAKE_C_STANDARD_REQUIRED True)
                            
                            # 包含头文件目录
                            include_directories(${CMAKE_SOURCE_DIR}/include)
                            
                            # 添加源文件
                            file(GLOB SOURCES "src/*.c")
                            
                            # 构建库
                            add_library(SampleColorViewer SHARED ${SOURCES})
                            
                            # 如果你有其他的依赖项,可以在这里添加
                            # target_link_libraries(SampleColorViewer PRIVATE SomeOtherLibrary)
                            

                            编译和链接

                            1. 生成构建文件:在主项目目录中运行 cmake . 或 cmake -B build(使用单独的构建目录)。
                            2. 编译项目:运行 cmake --build . 或 cmake --build build(如果你使用了单独的构建目录)。

                            这样,CMake 会处理 Sample-ColorViewer 子目录,并生成一个共享库(或静态库,如果你将 SHARED 改为 STATIC)。如果你的主项目需要链接这个库,你可以在主项目的 CMakeLists.txt 中添加相应的 target_link_libraries() 命令(如上面的注释所示)。

                            注意事项

                            • 确保 Sample-ColorViewer 目录中的 CMakeLists.txt 文件正确设置了包含目录和源文件。
                            • 如果你的库或应用程序需要链接其他外部库,确保在相应的 CMakeLists.txt 文件中添加 find_package() 和 target_link_libraries() 命令。
                            • 使用 file(GLOB ...) 来自动包含源文件是一种方便的方法,但它不如显式列出所有源文件那样明确和可靠。在大型项目中,最好显式列出所有源文件。

                            以上为生成回答,仅供参考~

                            我是小伊,已接入ChatGpt,所有回复,仅供参考~

                            1 条回复 最后回复 回复 引用 0
                            • 第一个帖子
                              最后一个帖子
                            皖ICP备16016415号-7
                            Powered by NodeBB | 鱼香ROS