从 MATLAB 调用 .c 文件会产生分段冲突

标签 c matlab mex

我想从 matlab 运行两个名为“hello1.c”和“hello2.c”的 C 程序。

我的hello1.c代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <mex.h>
#include <math.h>
#include "matrix.h"


void funcc(double **f, double **x, long n, long b, double lambda, double theta)
{
    long i;
    long j;
    double u,v,y,z,w;
    y = theta*lambda;
    w = lambda*lambda;
    z = 0.5*(theta+1.0)*w;

    u = 0.0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<b;j++)
        v = fabs(x[i][j]);
        if (v <= lambda)
            u += lambda*v;
        else if (v > y)
            u += z;
        else
            u += 0.5*(v*(2*y - v) - w)/(theta-1.0);
        }
    **f = u;
    return;
}


void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
    /*set up input arguments */
    double **x       =            mxGetPr(prhs[0]);
    long     n      =      (long)mxGetScalar(prhs[1]);
    long     b      =      (long)mxGetScalar(prhs[2]);
    double  lambda  =            mxGetScalar(prhs[3]);
    double  theta   =            mxGetScalar(prhs[4]);
    int     type    =       (int)mxGetScalar(prhs[5]);

    double **f;


    /* set up output arguments */
    plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);

    f=mxGetPr(plhs[0]);

    funcc(f, x, n, b, lambda, theta);
    }

我的hello2.c代码如下:

long mymin(double *x, long n)
{
    long i, ind;
    double temp;
    temp = x[0];
    ind = 0;
    for (i=1;i<n;i++)
    {
        if (x[i] < temp)
        {
            ind = i;
            temp = x[i];
        }

    }
    return ind;
}


        void funnn(double *x, double *d, long n, long b, double lambda, double theta)
        {
            long i;
            long j;
            double u,z,w;
            double xtemp[3],ytemp[3];
            z = theta*lambda;
            w = lambda*lambda;
            for(i=0;i<n;i++)
            {
                for(j=0;j<b;j++)
                u = fabs(d[j*n + i]);
                xtemp[0] = min(lambda,max(0,u - lambda));
                xtemp[1] = min(z,max(lambda,(u*(theta-1.0)-z)/(theta-2.0)));
                xtemp[2] = max(z,u);

                ytemp[0] = 0.5*(xtemp[0] - u)*(xtemp[0] - u) + lambda*xtemp[0];
                ytemp[1] = 0.5*(xtemp[1] - u)*(xtemp[1] - u) + 0.5*(xtemp[1]*(-xtemp[1] + 2*z) - w)/(theta-1.0);
                ytemp[2] = 0.5*(xtemp[2] - u)*(xtemp[2] - u) + 0.5*(theta+1.0)*w;
                x[j*n + i] = xtemp[mymin(ytemp,3)];
                x[j*n + i] = d[j*n + i]>= 0 ? x[j*n + i] : -x[j*n + i];
            }
            //return;
        }



        void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
        {
            /*set up input arguments */
            double* d       =            mxGetPr(prhs[0]);
            long     n      =      (long)mxGetScalar(prhs[1]);
            long     b      =      (long)mxGetScalar(prhs[2]);
            double  lambda  =            mxGetScalar(prhs[3]);
            double  theta   =            mxGetScalar(prhs[4]);

            double *x;


            /* set up output arguments */
            plhs[0] = mxCreateDoubleMatrix(n,b,mxREAL);

            x=mxGetPr(plhs[0]);

            funnn(x, d, n, b, lambda, theta);
        }

问题是,当我编译 MATLAB 代码时,它会调用我的 C 函数(当然我已经编写了 mex hello1.cmex hello2.c ),MATLAB 返回屏幕,显示 MATLAB 遇到内部问题,需要关闭。事实上,这个错误是在 MEX 文件运行时检测到的。

这是因为我的函数mexFunction写得不正确吗?任何知道如何编写 MEX 函数的人都可以帮助我吗?

任何帮助将不胜感激!

最佳答案

对于hello1.cmxGetPr在 MEX 中给你一个双指针。它为您提供一个单个指针,对于 2D 内存,它采用列主布局。您必须通过以下语法访问 2D 数组中的正确值,假设 ij 是您要访问的 2D 数组中的行和列:

ind = j*rows + i;

...因此,如果您想在 2D 数组 x 中找到位置 (i,j),只需执行以下操作:

double val = x[j*rows + i];

rows 是二维数组中的总行数。因此,您必须在代码中更正此问题才能正确访问二维数组。您还必须对 f 执行相同的操作。此外,您在第二个 for 循环周围缺少一对大括号,稍后我将解释原因。

因此,您的函数变为:

void funcc(double *f, double *x, long n, long b, double lambda, double theta) // Note change in function declaration
{
    long i;
    long j;
    double u,v,y,z,w;
    y = theta*lambda;
    w = lambda*lambda;
    z = 0.5*(theta+1.0)*w;

    u = 0.0;
    // n is the rows, b is the columns
    for(i=0;i<n;i++)
    {
        for(j=0;j<b;j++) { // Added
        v = fabs(x[j*n + i]); // Change here
        if (v <= lambda)
            u += lambda*v;
        else if (v > y)
            u += z;
        else
            u += 0.5*(v*(2*y - v) - w)/(theta-1.0);
        } // Added
    } 
    *f = u; // Change
    //return; // Superfluous
}

您的 mexFunction 现在变为:

void mexFunction (int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[])
{
    /*set up input arguments */
    double *x       =            mxGetPr(prhs[0]); // Change
    long     n      =      (long)mxGetScalar(prhs[1]);
    long     b      =      (long)mxGetScalar(prhs[2]);
    double  lambda  =            mxGetScalar(prhs[3]);
    double  theta   =            mxGetScalar(prhs[4]);
    int     type    =       (int)mxGetScalar(prhs[5]);

    double *f; // Change

    /* set up output arguments */
    plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);

    f=mxGetPr(plhs[0]);

    funcc(f, x, n, b, lambda, theta);
}

对于 hello2.c,除了第二个 for 循环之外,一切都很好。您只需要用花括号将代码块括起来即可:

           for(i=0;i<n;i++)
           {
                for(j=0;j<b;j++) { // added
                u = fabs(d[j*n + i]);
                xtemp[0] = min(lambda,max(0,u - lambda));
                xtemp[1] = min(z,max(lambda,(u*(theta-1.0)-z)/(theta-2.0)));
                xtemp[2] = max(z,u);

                ytemp[0] = 0.5*(xtemp[0] - u)*(xtemp[0] - u) + lambda*xtemp[0];
                ytemp[1] = 0.5*(xtemp[1] - u)*(xtemp[1] - u) + 0.5*(xtemp[1]*(-xtemp[1] + 2*z) - w)/(theta-1.0);
                ytemp[2] = 0.5*(xtemp[2] - u)*(xtemp[2] - u) + 0.5*(theta+1.0)*w;
                x[j*n + i] = xtemp[mymin(ytemp,3)];
                x[j*n + i] = d[j*n + i]>= 0 ? x[j*n + i] : -x[j*n + i];
                } //added
            } 

两个文件都需要额外的大括号,因为如果省略它们,C 只会将循环后的第一行视为循环体。 for 循环完成后的其余代码将被执行,而不是循环的一部分,这就是您出现段错误的原因。

关于从 MATLAB 调用 .c 文件会产生分段冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38484590/

相关文章:

matlab - 来自边缘列表的邻接矩阵(最好在 Matlab 中)

matlab - 使用 mexCallMATLAB 将 Double* 转换为 mxArray* 的最有效方法

MATLAB C/MEX 中的转换问题

C 和无限大小变量

c - 如何计算c中的微分系数

c++ - Matlab 无法正确初始化 C++ 共享库

matlab从关联矩阵绘制图形

c++ - 通过 Matlab mex 函数调用持久化 C++ 类实例

c - 指针声明的区别?

c - C 中 Makefile 的问题