想实现的功能为C#将一组点坐标信息传入给C++,并通过PCL相关函数进行贪婪投影三角化网格重建,最后返回一些想要的信息。不过因为想对报错的代码进行定位,就对要返回的信息做出了简化,直接返回一个int数据。
报错图片
C#源码
引入dll和C++的ReconstructMesh函数,并自定义结构体Point将点坐标信息录入
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace CallDllCSharp
{
internal class Program
{
[DllImport("PCL_DLL1.dll")]
public static extern int ReconstructMesh(Point[] points, int numPoints);
public struct Point
{
public float x, y, z;
}
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
GetIndices();
}
static void GetIndices()
{
Point[] points = new Point[]
{
new Point { x = 0.0f, y = 0.0f, z = 0.0f },
new Point { x = 0.0f, y = 0.0f, z = 1.0f },
new Point { x = 0.0f, y = 0.0f, z = 2.0f },
new Point { x = 0.0f, y = 1.0f, z = 0.0f },
new Point { x = 0.0f, y = 1.0f, z = 1.0f },
new Point { x = 0.0f, y = 1.0f, z = 2.0f },
new Point { x = 0.0f, y = 2.0f, z = 0.0f },
new Point { x = 0.0f, y = 2.0f, z = 1.0f },
new Point { x = 1.0f, y = 2.0f, z = 2.0f },
new Point { x = 1.0f, y = 0.0f, z = 0.0f },
new Point { x = 1.0f, y = 0.0f, z = 1.0f },
new Point { x = 1.0f, y = 0.0f, z = 2.0f },
new Point { x = 1.0f, y = 1.0f, z = 0.0f },
new Point { x = 1.0f, y = 1.0f, z = 2.0f },
new Point { x = 1.0f, y = 2.0f, z = 0.0f },
new Point { x = 1.0f, y = 2.0f, z = 1.0f },
new Point { x = 1.0f, y = 2.0f, z = 2.0f },
new Point { x = 2.0f, y = 0.0f, z = 0.0f },
new Point { x = 2.0f, y = 0.0f, z = 1.0f },
new Point { x = 2.0f, y = 0.0f, z = 2.0f },
new Point { x = 2.0f, y = 1.0f, z = 0.0f },
new Point { x = 2.0f, y = 1.0f, z = 1.0f },
new Point { x = 2.0f, y = 1.0f, z = 2.0f },
new Point { x = 2.0f, y = 2.0f, z = 0.0f },
new Point { x = 2.0f, y = 2.0f, z = 1.0f },
new Point { x = 2.0f, y = 2.0f, z = 2.0f },
};
int num = ReconstructMesh(points, points.Length);
Console.WriteLine(num);
}
}
}
C++源码
头文件
#pragma once
#ifdef _EXPORTING
#define _DLL_API _declspec(dllexport)
#else
#define _DLL_API _declspec(dllimport)
#endif
// 定义点的结构体
struct Point {
float x, y, z;
};
extern "C"
{
_DLL_API int ReconstructMesh(Point* points, int numPoints);
}
源文件
#include "MyC++.h"
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/search/kdtree.h>
#include <pcl/features/normal_3d.h>
#include <pcl/common/io.h>
#include <vld.h>
using namespace std;
int ReconstructMesh(Point* points, int numPoints)
{
// 转换输入点集为 PCL 点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
for (int i = 0; i < numPoints; ++i) {
cloud->emplace_back(pcl::PointXYZ(points[i].x, points[i].y, points[i].z));
}
// 创建法线估计对象
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;//设置法线估计对象
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
n.setInputCloud(cloud);
n.setSearchMethod(tree);
n.setKSearch(5);
n.compute(*normals);
// 合并 XYZ 和法线字段
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);
// 创建搜索树
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud(cloud_with_normals);
// 初始化对象
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;//定义三角化对象
pcl::PolygonMesh pclMesh;//存储最终三角化的网络模型
// 设置输入点云
gp3.setInputCloud(cloud_with_normals);
gp3.setSearchMethod(tree2);
// 设置参数
gp3.setSearchRadius(1.42);
gp3.setMu(2);
gp3.setMaximumNearestNeighbors(10);
gp3.setMaximumSurfaceAngle(M_PI / 2); // 45 degrees
gp3.setMinimumAngle(M_PI / 4); // 10 degrees
gp3.setMaximumAngle(M_PI / 2); // 120 degrees
gp3.setNormalConsistency(false);
try {
cout << "Before gp3.reconstruct" << endl;
gp3.reconstruct(pclMesh);
cout << "三角形数量:" << (int)pclMesh.polygons.size() << endl;
return pclMesh.polygons.size();
}
catch (const std::exception& e) {
cerr << e.what() << endl;
return -1;
}
}
可以看到,C++这边最终只是返回了一个int型的pclMesh.polygons.size(),值为35,最后C#作为启动项控制台输出的结果为"Before gp3.reconstruct"和"三角形数量:35"正常输出,但 35没有正常返回给C#,并弹出窗口报错。而且try-catch也没有捕捉到异常。
如果我把return任意一个数放在gp3.reconstruct(pclMesh);这行代码之前,就可以C#就可以正常得到这个数,比如以下修改后的代码可以返回“2”。
int ReconstructMesh(Point* points, int numPoints)
{
··· 其他代码···
// 设置参数
gp3.setSearchRadius(1.42);
gp3.setMu(2);
gp3.setMaximumNearestNeighbors(10);
gp3.setMaximumSurfaceAngle(M_PI / 2); // 45 degrees
gp3.setMinimumAngle(M_PI / 4); // 10 degrees
gp3.setMaximumAngle(M_PI / 2); // 120 degrees
gp3.setNormalConsistency(false);
try {
return 2;
gp3.reconstruct(pclMesh);
}
catch (const std::exception& e) {
cerr << e.what() << endl;
return -1;
}
}
问了一下New Bing说是内存泄漏,破坏堆的结构,使得堆指针无效之类的。各种尝试手动释放内存都没有解决,先埋个坑,看看大伙咋说