error LNK2019, 3 unresolved external symbols

4 ビュー (過去 30 日間)
Matthew
Matthew 2015 年 1 月 14 日
回答済み: Md.Salman 2016 年 8 月 25 日
Hi, I'm new to Matlab. I'm trying to build a C mex file. The C file and header files are all on the search path. I've been able to build C mex files, following the documents, but I'm not sure what's wrong here. Here's the error message I'm getting:
Error using mex Creating library DynamicProgrammingQ2.lib and object DynamicProgrammingQ2.exp DynamicProgrammingQ2.obj : error LNK2019: unresolved external symbol dp_costs referenced in function mexFunction DynamicProgrammingQ2.obj : error LNK2019: unresolved external symbol dp_build_gamma referenced in function mexFunction DynamicProgrammingQ2.obj : error LNK2019: unresolved external symbol dp_all_indexes referenced in function mexFunction DynamicProgrammingQ2.mexw64 : fatal error LNK1120: 3 unresolved externals
Please point me in the right direction.
  2 件のコメント
Geoff Hayes
Geoff Hayes 2015 年 1 月 14 日
Matthew - it sounds like your C code is referencing functions, for example dp_build_gamma (and a couple of others too), that you probably have defined in a header but you don't have the body for them. Could it be that there is a library that you should be linking into your build? Also, what is the mex command that you are using to build with?
Matthew
Matthew 2015 年 1 月 14 日
I'm using command:
mex 'T:\Matlab\SRVF_FDA\DynamicProgrammingQ2.c'
And here's the C code:
#include "mex.h"
#include <math.h>
#include "dp_grid.h"
/* Signature:
* function [G T] = dp_mex( Q1, T1, Q2, T2, tv1, tv2 )
* Arguments are checked in dp.m, not here. */
void mexFunction(int nlhs, mxArray *plhs[ ],int nrhs, const mxArray *prhs[ ]){
double *Q1 = 0;
double *T1 = 0;
double *Q2 = 0;
double *T2 = 0;
double *lam1 = 0;
double lam;
int nsamps1;
int nsamps2;
double *tv1 = 0;
double *tv2 = 0;
int *idxv1 = 0;
int *idxv2 = 0;
int ntv1;
int ntv2;
double *G = 0;
double *T = 0;
int Gsize;
int dim = 0;
double *E = 0; /* E[ntv1*j+i] = cost of best path to (tv1[i],tv2[j]) */
int *P = 0; /* P[ntv1*j+i] = predecessor of (tv1[i],tv2[j]) along best path */
double m, rootm;
int sr, sc; /* source row and column index */
int tr, tc; /* target row and column index */
int Galloc_size;
double *pres;
/* [G T dist] = dp_mex( Q1, T1, Q2, T2, tv1, tv2 ); */
Q1 = mxGetPr( prhs[0] );
T1 = mxGetPr( prhs[1] );
Q2 = mxGetPr( prhs[2] );
T2 = mxGetPr( prhs[3] );
tv1 = mxGetPr( prhs[4] );
tv2 = mxGetPr( prhs[5] );
lam1 = mxGetPr( prhs[6] );
lam = *lam1;
dim = mxGetM( prhs[0] );
nsamps1 = mxGetN( prhs[1] ); /* = columns(T1) = columns(Q1)+1 */
nsamps2 = mxGetN( prhs[3] ); /* = columns(T2) = columns(Q2)+1 */
ntv1 = mxGetN( prhs[4] );
ntv2 = mxGetN( prhs[5] );
Galloc_size = ntv1>ntv2 ? ntv1 : ntv2;
if ( !(idxv1=(int*)mxMalloc(ntv1*sizeof(int))) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "failed to allocate idxv1" );
goto cleanup;
}
if ( !(idxv2=(int*)mxMalloc(ntv2*sizeof(int))) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "failed to allocate idxv2" );
goto cleanup;
}
if ( !(E=(double*)mxMalloc(ntv1*ntv2*sizeof(double))) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "failed to allocate E" );
goto cleanup;
}
if ( !(P=(int*)mxCalloc(ntv1*ntv2,sizeof(int))) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "failed to allocate P" );
goto cleanup;
}
if ( !(plhs[0]=mxCreateDoubleMatrix(1,Galloc_size,mxREAL)) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "mxCreateDoubleMatrix failed" );
goto cleanup;
}
if ( !(plhs[1]=mxCreateDoubleMatrix(1,Galloc_size,mxREAL)) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "mxCreateDoubleMatrix failed" );
goto cleanup;
}
if ( !(plhs[2]=mxCreateDoubleScalar(0.0)) )
{
mexErrMsgIdAndTxt( "dp:AllocFailed", "mxCreateDoubleScalar failed" );
goto cleanup;
}
G = mxGetPr( plhs[0] );
T = mxGetPr( plhs[1] );
pres = mxGetPr( plhs[2] );
/* dp_costs() needs indexes for gridpoints precomputed */
dp_all_indexes( T1, nsamps1, tv1, ntv1, idxv1 );
dp_all_indexes( T2, nsamps2, tv2, ntv2, idxv2 );
/* Compute cost of best path from (0,0) to every other grid point */
*pres = dp_costs( Q1, T1, nsamps1, Q2, T2, nsamps2,
dim, tv1, idxv1, ntv1, tv2, idxv2, ntv2, E, P, lam );
/* Reconstruct best path from (0,0) to (1,1) */
Gsize = dp_build_gamma( P, tv1, ntv1, tv2, ntv2, G, T );
mxSetN( plhs[0], Gsize );
mxSetN( plhs[1], Gsize );
cleanup:
if ( idxv1 ) mxFree( idxv1 );
if ( idxv2 ) mxFree( idxv2 );
if ( E ) mxFree( E );
if ( P ) mxFree( P );
}
The header file is in the same directory on the search path. Here it is:
#ifndef DP_GRID_H
#define DP_GRID_H 1
/**
* Computes weights of all edges in the DP matching graph,
* which is needed for the Floyd-Warshall all-pairs shortest-path
* algorithm.
*
* The matrix of edge weights E must be allocated ahead of time by
* the caller. E is an ntv1 x ntv2 x ntv1 x ntv2 matrix. If i and k
* are column indices and j and l are row indices, then the weight of the
* edge from gridpoint (tv1[i],tv2[j]) to gridpoint (tv1[k],tv2[l]) is
* stored in E(j,i,l,k) when this function returns.
* Mapping:
* (j,i,l,k) :--> j*ntv1*ntv2*ntv1 +
* i*ntv2*ntv1 +
* l*ntv1 +
* k
*
* \param Q1 values of the first SRVF
* \param T1 changepoint parameters of the first SRVF
* \param nsamps1 the length of T1
* \param Q2 values of the second SRVF
* \param T2 changepoint parameters of the second SRVF
* \param nsamps2 the length of T2
* \param dim dimension of the ambient space
* \param tv1 the Q1 (column) parameter values for the DP grid
* \param idxv1 Q1 indexes for tv1, as computed by \c dp_all_indexes()
* \param ntv1 the length of tv1
* \param tv2 the Q2 (row) parameter values for the DP grid
* \param idxv2 Q2 indexes for tv2, as computed by \c dp_all_indexes()
* \param ntv2 the length of tv2
* \param E [output] pointer to the edge weight matrix. Must already be
* allocated, with size (ntv1*ntv2)^2.
*/
void dp_all_edge_weights(
double *Q1, double *T1, int nsamps1,
double *Q2, double *T2, int nsamps2,
int dim,
double *tv1, int *idxv1, int ntv1,
double *tv2, int *idxv2, int ntv2,
double *W, double lam );
/**
* Computes cost of best path from (0,0) to all other gridpoints.
*
* \param Q1 values of the first SRVF
* \param T1 changepoint parameters of the first SRVF
* \param nsamps1 the length of T1
* \param Q2 values of the second SRVF
* \param T2 changepoint parameters of the second SRVF
* \param nsamps2 the length of T2
* \param dim dimension of the ambient space
* \param tv1 the Q1 (column) parameter values for the DP grid
* \param idxv1 Q1 indexes for tv1, as computed by \c dp_all_indexes()
* \param ntv1 the length of tv1
* \param tv2 the Q2 (row) parameter values for the DP grid
* \param idxv2 Q2 indexes for tv2, as computed by \c dp_all_indexes()
* \param ntv2 the length of tv2
* \param E [output] on return, E[ntv2*i+j] holds the cost of the best
* path from (0,0) to (tv1[i],tv2[j]) in the grid.
* \param P [output] on return, P[ntv2*i+j] holds the predecessor of
* (tv1[i],tv2[j]). If predecessor is (tv1[k],tv2[l]), then
* P[ntv2*i+j] = k*ntv2+l.
* \return E[ntv1*ntv2-1], the cost of the best path from (tv1[0],tv2[0])
* to (tv1[ntv1-1],tv2[ntv2-1]).
*/
double dp_costs(
double *Q1, double *T1, int nsamps1,
double *Q2, double *T2, int nsamps2,
int dim,
double *tv1, int *idxv1, int ntv1,
double *tv2, int *idxv2, int ntv2,
double *E, int *P, double lam );
/**
* Computes the weight of the edge from (a,c) to (b,d) in the DP grid.
*
* \param Q1 values of the first SRVF
* \param T1 changepoint parameters of the first SRVF
* \param nsamps1 the length of T1
* \param Q2 values of the second SRVF
* \param T2 changepoint parameters of the second SRVF
* \param nsamps2 the length of T2
* \param dim dimension of the ambient space
* \param a source Q1 parameter
* \param b target Q1 parameter
* \param c source Q2 parameter
* \param d target Q2 parameter
* \param aidx index such that Q1[aidx] <= a < Q1[aidx+1]
* \param cidx index such that Q2[cidx] <= c < Q2[cidx+1]
*/
double dp_edge_weight(
double *Q1, double *T1, int nsamps1,
double *Q2, double *T2, int nsamps2,
int dim,
double a, double b,
double c, double d,
int aidx, int cidx, double lam );
/**
* Given predecessor table P, builds the piecewise-linear reparametrization
* function gamma.
*
* G and T must already be allocated with size max(ntv1,ntv2). The actual
* number of points on gamma will be the return value.
*
* \param P P[ntv2*i+j] holds the predecessor of (tv1[i],tv2[j]). If
* predecessor is (tv1[k],tv2[l]), then P[ntv2*i+j] = k*ntv2+l.
* \param tv1 the Q1 (column) parameter values for the DP grid
* \param ntv1 the length of tv1
* \param tv2 the Q2 (row) parameter values for the DP grid
* \param ntv2 the length of tv2
* \param G [output] reparametrization function values
* \param T [output] reparametrization changepoint parameters
* \return the length of G (same as length of T).
*/
int dp_build_gamma(
int *P,
double *tv1, int ntv1,
double *tv2, int ntv2,
double *G, double *T );
/**
* Given t in [0,1], return the integer i such that t lies in the interval
* [T[i],T[i+1]) (or returns n-2 if t==T[n-1]).
*
* \param T an increasing sequence
* \param n the length of T
* \param t the parameter value to lookup ( T[0] <= t <= T[n-1] ).
* \return the integer i such that t lies in the interval [T[i],T[i+1])
* (or n-2 if t==T[n-1]).
*/
int dp_lookup( double *T, int n, double t );
/**
* 1-D table lookup for a sorted array of query points.
*
* Given a partition p and an increasing sequence of numbers tv between
* p[0] and p[np-1], computes the sequence of indexes idxv such that for
* i=0,...,ntv-1, p[idxv[i]] <= tv[i] < p[idxv[i]+1]. If tv[i]==p[np-1],
* then idxv[i] will be set to np-2.
*
* \param p an increasing sequence (the table)
* \param np the length of \a p
* \param tv an increasing sequence (the query points)
* \param ntv the length of \a tv
* \param idxv [output] pre-allocated array of \a ntv ints to hold result
*/
void dp_all_indexes( double *p, int np, double *tv, int ntv, int *idxv );
#endif /* DP_GRID_H */
There are some other C files, but I think these are the only ones used in the function I'm trying to make.

サインインしてコメントする。

採用された回答

Geoff Hayes
Geoff Hayes 2015 年 1 月 15 日
Matthew - if you have other C files that have the function bodies for those function prototypes/signatures of dp_grid.h, then you need to include them when you build your mex function. This is why you are observing the unresolved external symbol errors. Try rebuilding as
mex T:\Matlab\SRVF_FDA\DynamicProgrammingQ2.c otherCFile.c
where otherCFile.c is the path to and the name of the C file that includes the missing function bodies.
  1 件のコメント
Matthew
Matthew 2015 年 1 月 15 日
Thank you. This worked

サインインしてコメントする。

その他の回答 (2 件)

Md.Salman
Md.Salman 2016 年 8 月 25 日
thanks

Md.Salman
Md.Salman 2016 年 8 月 25 日
Anyone who is trying to use the patchmatch algorithm and getting problems in building mex files using the .bat file, use the following commands from matlab command prompt.
>> mex knn.cpp mexutil.cpp nn.cpp nnmex.cpp patch.cpp vecnn.cpp simnn.cpp allegro_emu.cpp -output nnmex
>> mex knn.cpp mexutil.cpp nn.cpp votemex.cpp patch.cpp vecnn.cpp simnn.cpp allegro_emu.cpp -output votemex
It took me a long time trying to figure out. Posting so that can be helpful to others.

カテゴリ

Help Center および File ExchangeWrite C Functions Callable from MATLAB (MEX Files) についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by