Unity插件:Marshal c++ double*到c#中的double Array
Unity Plugin : Marshal C++ double* to double Array in C#
我正在与Unity和使用c++ Dll的插件系统作斗争。基本上我有一个Dll在c++中找到相机的外在参数知道内在参数。当我创建。exe时,函数运行得很顺利。
我想做的是通过c++中的Dll在Unity中使用该函数来获得存储在1D双数组中的外部参数。
我读了很多关于在Dll中导出函数和在c#中导入它们的内容,但是我花了4天的时间工作,没有任何效果。
我总是得到相同的错误:运行时错误和Unity崩溃(我认为内存访问问题)。
下面是c++代码
#include <opencv2opencv.hpp>
#include <stdio.h>
#ifdef CALIBRATION_EXPORTS
#define CALIBRATION_API __declspec(dllexport)
#else
#define CALIBRATION_API __declspec(dllimport)
#endif
using namespace cv;
using namespace std;
class CALIBRATION_API calib
{
public:
calib();
virtual ~calib();
void calcBoardCornerPosititions(Size boardSize, double squareSize, vector<Point3f>& corners);
Mat Nextimage(VideoCapture camera);
void find_extrinsic(double* Mat_Ext, double mat_int[], double mat_dist[], int size_ext, int size_int, int size_dist);
private :
VideoCapture camera;
};
extern "C" CALIBRATION_API calib* CreateCalib()
{
return new calib();
}
extern "C" CALIBRATION_API void DisposeCalib( calib* pObject)
{
if (pObject != NULL)
{
delete pObject;
pObject = NULL;
}
}
void calib::find_extrinsic(double *Mat_Ext, double mat_int[], double mat_dist[], int size_ext, int size_int, int size_dist)
{
if (size_ext == 16 && size_int == 9 && size_dist == 5)
{
Size boardSize = Size(9, 6);
double squareSize = 245;
//Matrices de résultats param ext
Mat_<double> rvecs_ext(3, 3);
Mat_<double> tvecs_ext(3, 1);
vector<Point3f> objectPoints_ext;
int id = 0;
Mat_<double> cameraMatrix(3, 3);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cameraMatrix.data[i, j] = mat_int[id];
id++;
}
}
Mat_<double> distCoeffs(5, 1);
for (int i = 0; i < 5; i++)
{
distCoeffs.data[i, 1] = mat_dist[i];
}
Mat result = Nextimage(camera);
Size imageSize = result.size();
vector<Point2f> pointBuf;
bool found = findChessboardCorners(result, boardSize, pointBuf, CALIB_CB_FAST_CHECK + CALIB_CB_FILTER_QUADS);
if (found)
{
calcBoardCornerPosititions(boardSize, squareSize, objectPoints_ext);
solvePnP(objectPoints_ext, pointBuf, cameraMatrix, distCoeffs, rvecs_ext, tvecs_ext, false, CV_ITERATIVE);
Mat_Ext[0] = rvecs_ext.at<double>(0, 0);
Mat_Ext[1] = rvecs_ext.at<double>(0, 1);
Mat_Ext[2] = rvecs_ext.at<double>(0, 2);
Mat_Ext[3] = tvecs_ext.at<double>(0, 0);
Mat_Ext[4] = rvecs_ext.at<double>(1, 0);
Mat_Ext[5] = rvecs_ext.at<double>(1, 1);
Mat_Ext[6] = rvecs_ext.at<double>(1, 2);
Mat_Ext[7] = tvecs_ext.at<double>(0, 2);
Mat_Ext[8] = rvecs_ext.at<double>(2, 0);
Mat_Ext[9] = rvecs_ext.at<double>(2, 1);
Mat_Ext[10] = rvecs_ext.at<double>(2, 2);
Mat_Ext[11] = rvecs_ext.at<double>(0, 3);
Mat_Ext[12] = rvecs_ext.at<double>(3, 0);
Mat_Ext[13] = rvecs_ext.at<double>(3, 1);
Mat_Ext[14] = rvecs_ext.at<double>(3, 2);
Mat_Ext[15] = 1;
}
}
}
}
extern"C" CALIBRATION_API void Call_find_extrinsic(calib* pObject, double *Mat_Ext, double mat_int[], double mat_dist[], int size_ext, int size_int, int size_dist)
{
if (pObject != NULL)
{
pObject->find_extrinsic(Mat_Ext, mat_int, mat_dist,size_ext,size_int,size_dist);
}
}
和相关c#代码:
[DllImport("Beta.dll")]
public static extern IntPtr CreateCalib();
[DllImport("Beta.dll")]
public static extern void DisposeCalib(IntPtr pCalibObject);
[DllImport("Beta.dll")]
public static extern void Call_find_extrinsic(IntPtr pCalibObject, double[] pMat_Ext, double[] mat_int, double[] mat_dist,
int size_ext, int size_int, int size_dist);
pCalibClass = CreateCalib();
double[]test_ext = new double[16];
Call_find_extrinsic(pCalibClass, test_ext,Intrinsic_mat,Dist_mat,test_ext.Length,Intrinsic_mat.Length,Dist_mat.Length);
我尝试用find_extrinsic方法计算的值填充test_ext。
你能帮我解决这个问题吗?谢谢你!
rvecs_ext不应该是一个3x3矩阵,而是一个3x1向量。因此,当您访问禁止的内存空间时,它会崩溃。
3x1向量为旋转矩阵的对角线,其他元素视为null。为什么?看看这个
c++和c#函数的调用约定不匹配,__cdecl是C和c++程序的默认调用约定,而__stdcall是默认的,如果你没有在[DllImport]属性中显式指定它。如果约定不匹配,就会因为栈损坏而导致程序崩溃。
详情请参考此
所以你应该在[DllImport]声明中添加CallingConvention = CallingConvention.Cdecl
相关文章:
- 在c++中为double类型的数组创建一个unique_ptr
- 比较C++中的double,同行评审
- "double x = 0.0d;"中的"d"是g++扩展吗?
- C++ 类型 'complex<double>' 中类中的复杂初始化不提供调用运算符
- 使用词法强制转换在'string to double'中设置双精度变量的精度
- 使用std :: filesystem :: path中的double
- 如何将JSON文件中的数据转换为值(double,int ..)
- C++:无法使用条件类型在模板函数中使用 'double' 类型的 lvalue 初始化 'char*' 类型的参数
- 代码:: blocks printf double windows中的固定精度
- "double free or curruption " C++ 中的错误
- 为什么双精度 a=(double)('z'/'A') 只给出C++中的整数部分?
- 如何在不使用min_element C++的情况下找到向量中的最小值和最大值<double>
- 如何擦除double for循环中的矢量元素
- C++将double序列化为little-endian中的二进制文件
- 如何清除通用 C++ 代码中的“double”
- 有没有办法将 OpenCV 中的 minAreaRect 与 double 一起使用
- 如何将'on double clicked'事件添加到QTableWidget中的整行?
- 如何将"double*"传递给类函数,并将该值应用于该类中的另一个"double*"
- 在这个输入中,float和double之间的区别是什么
- <Double> LabView 中的原生向量作为参数/返回