丢丢丢丢丢丢~ 2025-12-03 10:18 采纳率: 36.4%
浏览 9

pcl代码生成dll,调用函数闪退


1. DLL 代码
1.1 MyDll.h
#pragma once

#ifdef MYDLL_EXPORTS  // DLL 导出宏
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>

extern "C" {
    MYDLL_API void LoadPLYFile(const char* filename);
}

1.2 MyDll.cpp
#include "MyDll.h"
#include <iostream>

void LoadPLYFile(const char* filename) {
    // 创建一个点云对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    // 读取 PLY 文件
    if (pcl::io::loadPLYFile<pcl::PointXYZ>(filename, *cloud) == -1) {
        std::cerr << "无法读取文件: " << filename << std::endl;
        return;
    }

    // 打印点云的大小
    std::cout << "成功读取点云!点数: " << cloud->size() << std::endl;
}
2. EXE 代码
2.1 main.cpp

这是一个简单的 EXE 程序,它调用你在 DLL 中实现的 LoadPLYFile 函数。

#include <iostream>
#include "MyDll.h"

int main() {
    const char* filename = "3.ply";  // 指定 .ply 文件路径

    // 调用 DLL 中的函数来加载 PLY 文件
    LoadPLYFile(filename);

    return 0;
}

这个读取ply代码,一运行就闪退,包括其他所有pcl函数都会如此,但我exe本身去使用就没问题,dll里面使用就有问题,exe和dll的编译都是在同一电脑的pcl1.4版本,都是release下/MD

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2025-12-03 10:22
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你遇到的问题是 DLL 中调用 PCL 函数导致程序闪退,而 EXE 本身直接使用 PCL 没问题。这表明问题可能出在 DLL 和 EXE 的运行时库不一致PCL 库的依赖关系未正确导出或链接,或者 DLL 中的 PCL 代码与 EXE 中的 PCL 版本不兼容


    ✅ 问题分析

    1. DLL 和 EXE 使用了不同的运行时库(CRT)配置

      • 例如:DLL 使用的是 /MD(动态链接到 CRT),而 EXE 使用的是 /MT(静态链接 CRT),这会导致内存分配和释放不一致,从而引发崩溃。
      • 在你的描述中提到“都是 release 下 /MD”,所以这个可能性较低,但仍需确认。
    2. PCL 库未被正确导出或链接

      • PCL 是一个复杂的 C++ 库,包含多个依赖项(如 Eigen、OpenNI、VTK 等)。如果 DLL 中没有正确处理这些依赖项,可能会导致加载失败或运行时错误。
    3. DLL 中的函数未正确暴露或调用方式有误

      • 例如,DLL 中的 LoadPLYFile 函数虽然定义为 extern "C",但内部使用了 C++ 类型(如 pcl::PointCloud<pcl::PointXYZ>),可能导致符号冲突或堆栈异常。
    4. PCL 的版本不一致

      • 即使你在同一台电脑上编译,也可能存在多个 PCL 版本(如系统安装的和项目中的),导致 DLL 和 EXE 使用了不同版本的 PCL 库。

    🔧 解决方案

    1. 确保 EXE 和 DLL 使用相同的运行时库配置

    • 检查编译器设置

      • 打开 Visual Studio 项目属性(Project Properties)。
      • 确认 EXE 和 DLL 的 C/C++ > Code Generation > Runtime Library 都是 /MD(Release)。
      • 如果其中一个用了 /MT,则需要统一改为 /MD
    • 确保所有依赖库也使用相同的 CRT 配置


    2. 修复 PCL 依赖问题

    • 确保 DLL 中的 PCL 依赖项被正确导出或链接

      • PCL 本身是静态库或动态库?如果是动态库(DLL),需要确保它们被正确加载。
      • 如果使用的是 PCL 的静态库(.lib 文件),需要在 DLL 项目中正确链接这些库,并且确保它们的 CRT 配置与主程序一致。
    • 在 DLL 项目中添加 PCL 的依赖项

      • 在 Visual Studio 中,右键项目 -> 属性 -> 配置属性 -> VC++ 目录 -> 包含目录,添加 PCL 的头文件路径。
      • 在链接器 -> 输入中,添加 PCL 的 .lib 文件(如 pcl_common.lib, pcl_io.lib 等)。

    3. 修改 DLL 函数以避免 C++ 类型问题

    由于 PCL 是 C++ 库,而你希望通过 extern "C" 导出函数,建议对 PCL 的对象进行封装,避免直接传递 C++ 对象(如 pcl::PointCloud<pcl::PointXYZ>)作为参数。

    ✅ 建议修改如下:

    3.1 MyDll.h
    #pragma once
    
    #ifdef MYDLL_EXPORTS
    #define MYDLL_API __declspec(dllexport)
    #else
    #define MYDLL_API __declspec(dllimport)
    #endif
    
    #include <string>
    
    extern "C" {
        // 定义一个结构体用于传递点云数据
        struct PointCloudData {
            int size;
            float* x;
            float* y;
            float* z;
        };
    
        MYDLL_API void LoadPLYFile(const char* filename);
        MYDLL_API PointCloudData GetPointCloud();
    }
    
    3.2 MyDll.cpp
    #include "MyDll.h"
    #include <pcl/point_cloud.h>
    #include <pcl/point_types.h>
    #include <pcl/io/ply_io.h>
    #include <vector>
    
    // 全局变量存储点云数据
    PointCloudData g_pointCloud;
    
    void LoadPLYFile(const char* filename) {
        pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    
        if (pcl::io::loadPLYFile<pcl::PointXYZ>(filename, *cloud) == -1) {
            std::cerr << "无法读取文件: " << filename << std::endl;
            return;
        }
    
        // 将点云数据拷贝到全局结构体中
        g_pointCloud.size = cloud->size();
        g_pointCloud.x = new float[g_pointCloud.size];
        g_pointCloud.y = new float[g_pointCloud.size];
        g_pointCloud.z = new float[g_pointCloud.size];
    
        for (int i = 0; i < g_pointCloud.size; ++i) {
            g_pointCloud.x[i] = cloud->points[i].x;
            g_pointCloud.y[i] = cloud->points[i].y;
            g_pointCloud.z[i] = cloud->points[i].z;
        }
    }
    
    PointCloudData GetPointCloud() {
        return g_pointCloud;
    }
    
    3.3 main.cpp
    #include <iostream>
    #include "MyDll.h"
    
    int main() {
        const char* filename = "3.ply";
    
        LoadPLYFile(filename);
    
        PointCloudData data = GetPointCloud();
    
        std::cout << "成功读取点云!点数: " << data.size << std::endl;
    
        // 释放内存
        delete[] data.x;
        delete[] data.y;
        delete[] data.z;
    
        return 0;
    }
    

    4. 确保 PCL 依赖项被正确加载

    • 将 PCL 的 DLL 文件(如 pcl_common.dll, pcl_io.dll)复制到 EXE 所在目录
    • 或者,将 PCL 的 DLL 路径添加到系统的 PATH 环境变量中。

    5. 检查 PCL 版本一致性

    • 确保 EXE 和 DLL 使用的是同一个 PCL 版本(如 PCL 1.4)。
    • 可以通过以下命令验证 PCL 版本:
      pcl_version
      

    🛠️ 最终建议总结

    | 问题 | 解决方案 | |------|----------| | DLL 与 EXE 的 CRT 不一致 | 确保两者都使用 /MD 编译 | | PCL 依赖未正确链接 | 在 DLL 项目中正确链接 PCL 的 .lib 文件 | | C++ 对象未正确封装 | 将 PCL 对象封装为 C 风格结构体,避免直接传递 C++ 类型 | | PCL 依赖 DLL 未正确加载 | 将 PCL 的 DLL 文件放在可执行文件目录下 | | PCL 版本不一致 | 确保 EXE 和 DLL 使用相同版本的 PCL |


    如果你仍然遇到问题,可以尝试以下调试方法:

    • 使用 Visual Studio 的调试器 查看崩溃位置。
    • 使用 Dependency Walker 检查 DLL 是否缺少依赖项。
    • LoadPLYFile 函数中添加日志输出,确认是否能正常进入该函数。

    如需进一步帮助,请提供完整的编译日志和错误信息。

    评论

报告相同问题?

问题事件

  • 创建了问题 12月3日