我正在尝试编写一个mex文件,在评估mex时,每次运行MATLAB都会崩溃。这是我编写的C ++代码的一部分:
void mexFunction(mwSize nlhs, mxArray *plhs[],
mwSize nrhs, const mxArray *prhs[]){
vector<int> *NNLt;
double *NNLtout;
Vector *V;
Vector *Fb;
mwSize *sn;
mwSize nsn;
mwSize nf;
double hs;
double bw;
double mw;
mwSize ncols;
mwSize i;
double *NNLtoutt;
/* check for proper number of arguments */
if(nrhs!=9) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Nine inputs required.");
}
if(nlhs!=1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required.");
}
/* get the value of the scalar input */
nsn = mxGetScalar(prhs[4]);
nf = mxGetScalar(prhs[5]);
hs = mxGetScalar(prhs[6]);
bw = mxGetScalar(prhs[7]);
mw = mxGetScalar(prhs[8]);
/* create a pointer to the real data in the input matrix */
NNLt = (vector<int> *)mxGetData(prhs[0]);
V = (Vector *)mxGetData(prhs[1]);
Fb =(Vector *)mxGetData(prhs[2]);
sn = (mwSize *)mxGetData(prhs[3]);
/* call the computational routine */
createNNLtriangle(NNLt, V, Fb, sn, nsn, nf, hs, bw, mw);
/* create the output matrix */
plhs[0] = mxCreateCellMatrix(nsn,50);
for(i=0;i<nsn;i++){
mxArray* tmp = mxCreateDoubleMatrix(1, NNLt[i].size(), mxREAL);
copy(NNLt[i].begin(), NNLt[i].end(), mxGetPr(tmp));
mxSetCell(plhs[0], i, tmp);
mxFree(tmp);
}}
所以,我遇到以下错误:
------------------------------------------------------------------------ Segmentation violation detected at Thu Aug 2 14:41:25 2018 ------------------------------------------------------------------------ ... Stack Trace (from fault): [ 0] 0x00007f0b0c635426 /home/user/dir/createNNLtriangle.mexa64+00005158 [ 1] 0x00007f0b0c635893 /home/user/dir/createNNLtriangle.mexa64+00006291 mexFunction+00000240 [ 2] 0x00007f0c562cac4a /home/user/bin/glnxa64/libmex.so+00142410 mexRunMexFile+00000090 ...
对于我们造成的混乱,同事们的澄清和其他问题,我们深表歉意。
您可以找到我们如何定义“ NNLt”。而这里的“ tmp”是什么意思?
std::copy(mxGetPr(tmp), mxGetPr(tmp)+N, NNLt.begin());
下面是Mexfile中的cpp函数,它在MexFunction之前:
#include "mex.h"
#include "matrix.h"
#include <omp.h>
#include "vema.h"s
#include "eig3.h"
#include <stdlib.h>
#include <iostream>
#include <cmath>
#include <vector>
#include <fstream>
#include <iomanip>
#include <sys/types.h>
#include <sys/stat.h>
using namespace std;
Vector closestPointTriangle(Vector&, Vector&, Vector&, Vector&, double&, double&, double&);
// Generates pomwSize-triangle proximity lists using the linked cell algorithm
void createNNLtriangle(vector<int>* NNLt, Vector* Ut, Vector* faces, int* SN, mwSize nsn, mwSize nf, double hs, double bw, double mw) {
int mx = max(1, (int)(bw/mw)); // ** = 40 cells bw=3.2, mw=0.08
vector<int> head(mx*mx*mx, -1);
vector<int> list(nf);
// std::vector<int> head(mx*mx*mx, -1); //****** mx*mx*mx cells nomber, size mx*mx*mx vector with all values are -1, 40*40*40 = 64000
// std::vector<int> list(nf); // **** nf = 101882
int xa, ya, za, xi, yi, zi;
double ub, vb, wb;
int pt, tri;
Vector cog;
for (int i = 0; i < nf; i++) { // Divide triangle faces mwSizeo cells, i index of face
//Vector cog = (Ut[faces[i].n1] + Ut[faces[i].n2] + Ut[faces[i].n3])/3.0;
cog = (Ut[(int)faces[i].x] + Ut[(int)faces[i].y] + Ut[(int)faces[i].z])/3.0;
int xa = (int)((cog.x + 0.5*bw)/bw*mx);
int ya = (int)((cog.y + 0.5*bw)/bw*mx);
int za = (int)((cog.z + 0.5*bw)/bw*mx);
int tmp = mx*mx*za + mx*ya + xa; // *** 1641838 > 64000
list[i]=head[mx*mx*za + mx*ya + xa];
head[mx*mx*za + mx*ya + xa] = i;
}
#pragma omp parallel for
for (int i = 0; i < nsn; i++) { // Search cells around each pomwSize and build proximity list
int pt = SN[i];
NNLt[i].clear();
int xa = (int)((Ut[pt].x + 0.5*bw)/bw*mx);
int ya = (int)((Ut[pt].y + 0.5*bw)/bw*mx);
int za = (int)((Ut[pt].z + 0.5*bw)/bw*mx);
for (int xi = max(0, xa-1); xi <= min(mx-1, xa+1); xi++)// *** Browse head list
for (int yi = max(0, ya-1); yi <= min(mx-1, ya+1); yi++)
for (int zi = max(0, za-1); zi <= min(mx-1, za+1); zi++) {
int tri = head[mx*mx*zi + mx*yi + xi];
while (tri != -1) {
if ( pt != (int)faces[tri].x && pt != (int)faces[tri].y && pt != (int)faces[tri].z ) {
if ( (closestPointTriangle(Ut[pt], Ut[(int)faces[tri].x], Ut[(int)faces[tri].y], Ut[(int)faces[tri].z], ub, vb, wb) - Ut[pt]).length() < hs) {
NNLt[i].push_back(tri);
}
}
tri = list[tri];
}
}
}
}
// Returns the closest pomwSize of triangle abc to pomwSize p ***** a or b or c, if not, pt projection through the barycenter inside the triangle
Vector closestPointTriangle(Vector& p, Vector& a, Vector& b, Vector& c, double& u, double& v, double& w) {
Vector ab = b - a;
Vector ac = c - a;
Vector ap = p - a;
double d1 = ab.dot(ap);
double d2 = ac.dot(ap);
if (d1 <= 0.0 && d2 <= 0.0) {
u = 1.0;
v = 0.0;
w = 0.0;
return a;
}
Vector bp = p - b;
double d3 = ab.dot(bp);
double d4 = ac.dot(bp);
if (d3 >= 0.0 && d4 <= d3) {
u = 0.0;
v = 1.0;
w = 0.0;
return b;
}
double vc = d1*d4 - d3*d2;
if (vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0) {
v = d1 / (d1 - d3);
u = 1.0 - v;
w = 0.0;
return a + ab * v;
}
Vector cp = p - c;
double d5 = ab.dot(cp);
double d6 = ac.dot(cp);
if (d6 >= 0.0 && d5 <= d6) {
u = 0.0;
v = 0.0;
w = 1.0;
return c;
}
double vb = d5*d2 - d1*d6;
if (vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0) {
w = d2 / (d2 - d6);
u = 1.0 - w;
v = 0.0;
return a + ac * w;
}
double va = d3*d6 - d5*d4;
if (va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0) {
w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
u = 0.0;
v = 1.0 - w;
return b + (c - b) * w;
}
double denom = 1.0 / (va + vb + vc);
v = vb * denom;
w = vc * denom;
u = 1.0 - v - w;
return a + ab * v + ac * w;
}
下面是在Matlab中调用Mexfile的部分:
NNLt = cell(1,nsn);
V = A(1:n,1:3); //A: Matrix
Fb = A(n:2*n,1:3);
nf = size(Fb,1);
sn = B(1,:); //B: Matrix
parfor i = 1:nsn
maxDist = max(maxDist, length(V(sn(i),:) - Vtold(i,:)));
end
if maxDist > 0.5*(hs-hc)
[NNLt] = createNNLtriangle(NNLt, V, Fb, sn, nsn, nf, hs, bw, mw);
for i = 1:nsn
Vtold(i,:) = V(sn(i),:);
end
end
最后,这是我们的V和Fb定义的“ Vector *”类:
class Vector{
public:
double x, y, z;
Vector(): x(0.0), y(0.0), z(0.0) {};
Vector(double ax, double ay, double az): x(ax), y(ay), z(az) {};
double length(){
return sqrt(x*x + y*y + z*z);
}
double dot(const Vector& b){
return x*b.x + y*b.y + z*b.z;
}
Vector cross(const Vector& b){
return Vector(y*b.z - z*b.y, z*b.x - x*b.z, x*b.y - y*b.x);
}
void normalize(){
double temp = 1.0/length();
x *= temp;
y *= temp;
z *= temp;
}
void clear(){
x = y = z = 0.0;
}
Vector& operator+= (const Vector& b){
x += b.x;
y += b.y;
z += b.z;
return *this;
}
Vector& operator-= (const Vector& b){
x -= b.x;
y -= b.y;
z -= b.z;
return *this;
}
Vector& operator*= (const double& c){
x *= c;
y *= c;
z *= c;
return *this;
}
Vector& operator/= (const double& c){
x /= c;
y /= c;
z /= c;
return *this;
}
Vector operator+ (const Vector& b){
Vector r = *this;
return r += b;
}
Vector operator- (const Vector& b){
Vector r = *this;
return r -= b;
}
Vector operator* (const double& c){
Vector r = *this;
return r *= c;
}
Vector operator/ (const double& c){
Vector r = *this;
return r /= c;
}
};
再次很抱歉! 谢谢, 干杯
答案 0 :(得分:2)
与rahnema1 said in a comment一样,您无法将mxGetData
的输出强制转换为所需的任何指针类型。此输出指向mxArray
的数据,您需要这样读取它。
例如,
NNLt = (vector<int> *)mxGetData(prhs[0]);
vector<int>
是特定的C ++数据结构,您正在将MATLAB数组中的数据重新解释为C ++数据结构。该数据结构的元素之一是指向数据的指针,因此您正在将(大概)双浮点值重新解释为指针,然后访问该指针,显然会导致崩溃。
您对Vector*
的强制转换也是如此,尽管我不知道此类是什么。
相反,首先请确保输入的类型正确,然后将数据复制到以下位置:
if(!mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","First input must be a double array.");
}
std::size_t N = mxGetNumberOfElements(prhs[0]);
std::vector<int> NNLt(N);
std::copy(mxGetPr(prhs[0]), mxGetPr(prhs[0])+N, NNLt.begin());
但是,在您的其余代码中,NNLt
似乎是向量的向量,而不是单个向量。 createNNLtriangle
函数是否取自here?看起来像是对C和C ++的可怕破坏。
也许您然后需要在此处执行以下操作:
if(!mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","First input must be a double array.");
}
std::size_t M = mxGetM(prhs[0]); // number of rows
std::size_t N = mxGetN(prhs[0]); // number of columns
std::vector<std::vector<int>> NNLt(N, std::vector<int>(M));
double* ptr = mxGetPr(prhs[0]);
for(std::size_t ii = 0; ii < N; ++ii) {
std::copy(ptr, ptr+M, NNLt[ii].begin());
ptr += M;
}
// mwSize nsn = static_cast<mwSize>(mxGetScalar(prhs[4])); // Ignore this value!
// ... read the other values here in the same way
createNNLtriangle(NNLt.data(), V, Fb, sn, N, nf, hs, bw, mw);
// ^^^^^^^^^^^ ^--- NOTE!
还要注意,第三个参数Fb
是vector<Face>
,而不是Vector*
。您将必须弄清楚如何转换Vector*
和vector<Face>
,它将涉及如上所述的大量代码,而不仅仅是转换指针!
第四个参数是int*
,而不是mwSize*
:
sn = (mwSize *)mxGetData(prhs[3]);
您需要确保prhs[3]
实际上包含一个int32
矩阵,然后才能将其指针强制转换为int*
。否则,您将必须像上面一样复制数据。
还要仔细检查所有其他参数,以确保传递正确的类型。设置编译器以警告所有隐式强制转换,然后注意所有这些警告。这些警告中的每一个都是导致您的程序在运行时崩溃的潜在原因。全部解决!