MEX error LNK2019:unresolved symbol
7 views (last 30 days)
Show older comments
Hello and thank you in advance for your help
I am having an issue compiling the following mex file (NLopt library) :
/* Copyright (c) 2007-2014 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Matlab MEX interface to NLopt, and in particular to nlopt_optimize */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <mex.h>
#include "nlopt.h"
#define CHECK0(cond, msg) if (!(cond)) mexErrMsgTxt(msg);
static double struct_val_default(const mxArray *s, const char *name, double dflt)
{
mxArray *val = mxGetField(s, 0, name);
if (val) {
CHECK0(mxIsNumeric(val) && !mxIsComplex(val)
&& mxGetM(val) * mxGetN(val) == 1,
"opt fields, other than xtol_abs, must be real scalars");
return mxGetScalar(val);
}
return dflt;
}
static double *struct_arrval(const mxArray *s, const char *name, unsigned n,
double *dflt)
{
mxArray *val = mxGetField(s, 0, name);
if (val) {
CHECK0(mxIsNumeric(val) && !mxIsComplex(val)
&& mxGetM(val) * mxGetN(val) == n,
"opt vector field is not of length n");
return mxGetPr(val);
}
return dflt;
}
static mxArray *struct_funcval(const mxArray *s, const char *name)
{
mxArray *val = mxGetField(s, 0, name);
if (val) {
CHECK0(mxIsChar(val) || mxIsFunctionHandle(val),
"opt function field is not a function handle/name");
return val;
}
return NULL;
}
static double *fill(double *arr, unsigned n, double val)
{
unsigned i;
for (i = 0; i < n; ++i) arr[i] = val;
return arr;
}
#define FLEN 128 /* max length of user function name */
#define MAXRHS 3 /* max nrhs for user function */
typedef struct user_function_data_s {
char f[FLEN];
mxArray *plhs[2];
mxArray *prhs[MAXRHS];
int xrhs, nrhs;
int verbose, neval;
struct user_function_data_s *dpre;
nlopt_opt opt;
} user_function_data;
static double user_function(unsigned n, const double *x,
double *gradient, /* NULL if not needed */
void *d_)
{
user_function_data *d = (user_function_data *) d_;
double f;
d->plhs[0] = d->plhs[1] = NULL;
memcpy(mxGetPr(d->prhs[d->xrhs]), x, n * sizeof(double));
CHECK0(0 == mexCallMATLAB(gradient ? 2 : 1, d->plhs,
d->nrhs, d->prhs, d->f),
"error calling user function");
CHECK0(mxIsNumeric(d->plhs[0]) && !mxIsComplex(d->plhs[0])
&& mxGetM(d->plhs[0]) * mxGetN(d->plhs[0]) == 1,
"user function must return real scalar");
f = mxGetScalar(d->plhs[0]);
mxDestroyArray(d->plhs[0]);
if (gradient) {
CHECK0(mxIsDouble(d->plhs[1]) && !mxIsComplex(d->plhs[1])
&& (mxGetM(d->plhs[1]) == 1 || mxGetN(d->plhs[1]) == 1)
&& mxGetM(d->plhs[1]) * mxGetN(d->plhs[1]) == n,
"gradient vector from user function is the wrong size");
memcpy(gradient, mxGetPr(d->plhs[1]), n * sizeof(double));
mxDestroyArray(d->plhs[1]);
}
d->neval++;
if (d->verbose) mexPrintf("nlopt_optimize eval #%d: %g\n", d->neval, f);
if (mxIsNaN(f)) nlopt_force_stop(d->opt);
return f;
}
static void user_pre(unsigned n, const double *x, const double *v,
double *vpre, void *d_)
{
user_function_data *d = ((user_function_data *) d_)->dpre;
d->plhs[0] = d->plhs[1] = NULL;
memcpy(mxGetPr(d->prhs[d->xrhs]), x, n * sizeof(double));
memcpy(mxGetPr(d->prhs[d->xrhs + 1]), v, n * sizeof(double));
CHECK0(0 == mexCallMATLAB(1, d->plhs,
d->nrhs, d->prhs, d->f),
"error calling user function");
CHECK0(mxIsDouble(d->plhs[0]) && !mxIsComplex(d->plhs[0])
&& (mxGetM(d->plhs[0]) == 1 || mxGetN(d->plhs[0]) == 1)
&& mxGetM(d->plhs[0]) * mxGetN(d->plhs[0]) == n,
"vpre vector from user function is the wrong size");
memcpy(vpre, mxGetPr(d->plhs[0]), n * sizeof(double));
mxDestroyArray(d->plhs[0]);
d->neval++;
if (d->verbose) mexPrintf("nlopt_optimize precond eval #%d\n", d->neval);
}
#define CHECK1(cond, msg) if (!(cond)) { mxFree(tmp); nlopt_destroy(opt); nlopt_destroy(local_opt); mexWarnMsgTxt(msg); return NULL; };
nlopt_opt make_opt(const mxArray *opts, unsigned n)
{
nlopt_opt opt = NULL, local_opt = NULL;
nlopt_algorithm algorithm;
double *tmp = NULL;
unsigned i;
algorithm = (nlopt_algorithm)
struct_val_default(opts, "algorithm", NLOPT_NUM_ALGORITHMS);
CHECK1(((int)algorithm) >= 0 && algorithm < NLOPT_NUM_ALGORITHMS,
"invalid opt.algorithm");
tmp = (double *) mxCalloc(n, sizeof(double));
opt = nlopt_create(algorithm, n);
CHECK1(opt, "nlopt: out of memory");
nlopt_set_lower_bounds(opt, struct_arrval(opts, "lower_bounds", n,
fill(tmp, n, -HUGE_VAL)));
nlopt_set_upper_bounds(opt, struct_arrval(opts, "upper_bounds", n,
fill(tmp, n, +HUGE_VAL)));
nlopt_set_stopval(opt, struct_val_default(opts, "stopval", -HUGE_VAL));
nlopt_set_ftol_rel(opt, struct_val_default(opts, "ftol_rel", 0.0));
nlopt_set_ftol_abs(opt, struct_val_default(opts, "ftol_abs", 0.0));
nlopt_set_xtol_rel(opt, struct_val_default(opts, "xtol_rel", 0.0));
nlopt_set_xtol_abs(opt, struct_arrval(opts, "xtol_abs", n,
fill(tmp, n, 0.0)));
nlopt_set_x_weights(opt, struct_arrval(opts, "x_weights", n,
fill(tmp, n, 1.0)));
nlopt_set_maxeval(opt, struct_val_default(opts, "maxeval", 0.0) < 0 ?
0 : struct_val_default(opts, "maxeval", 0.0));
nlopt_set_maxtime(opt, struct_val_default(opts, "maxtime", 0.0));
nlopt_set_population(opt, struct_val_default(opts, "population", 0));
nlopt_set_vector_storage(opt, struct_val_default(opts, "vector_storage", 0));
if (struct_arrval(opts, "initial_step", n, NULL))
nlopt_set_initial_step(opt,
struct_arrval(opts, "initial_step", n, NULL));
if (mxGetField(opts, 0, "local_optimizer")) {
const mxArray *local_opts = mxGetField(opts, 0, "local_optimizer");
CHECK1(mxIsStruct(local_opts),
"opt.local_optimizer must be a structure");
CHECK1(local_opt = make_opt(local_opts, n),
"error initializing local optimizer");
nlopt_set_local_optimizer(opt, local_opt);
nlopt_destroy(local_opt); local_opt = NULL;
}
mxFree(tmp);
return opt;
}
#define CHECK(cond, msg) if (!(cond)) { mxFree(dh); mxFree(dfc); nlopt_destroy(opt); mexErrMsgTxt(msg); }
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
unsigned n;
double *x, *x0, opt_f;
nlopt_result ret;
mxArray *x_mx, *mx;
user_function_data d, dpre, *dfc = NULL, *dh = NULL;
nlopt_opt opt = NULL;
CHECK(nrhs == 2 && nlhs <= 3, "wrong number of arguments");
/* options = prhs[0] */
CHECK(mxIsStruct(prhs[0]), "opt must be a struct");
/* x0 = prhs[1] */
CHECK(mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1])
&& (mxGetM(prhs[1]) == 1 || mxGetN(prhs[1]) == 1),
"x must be real row or column vector");
n = mxGetM(prhs[1]) * mxGetN(prhs[1]),
x0 = mxGetPr(prhs[1]);
CHECK(opt = make_opt(prhs[0], n), "error initializing nlopt options");
d.neval = 0;
d.verbose = (int) struct_val_default(prhs[0], "verbose", 0);
d.opt = opt;
/* function f = prhs[1] */
mx = struct_funcval(prhs[0], "min_objective");
if (!mx) mx = struct_funcval(prhs[0], "max_objective");
CHECK(mx, "either opt.min_objective or opt.max_objective must exist");
if (mxIsChar(mx)) {
CHECK(mxGetString(mx, d.f, FLEN) == 0,
"error reading function name string (too long?)");
d.nrhs = 1;
d.xrhs = 0;
}
else {
d.prhs[0] = mx;
strcpy(d.f, "feval");
d.nrhs = 2;
d.xrhs = 1;
}
d.prhs[d.xrhs] = mxCreateDoubleMatrix(1, n, mxREAL);
if ((mx = struct_funcval(prhs[0], "pre"))) {
CHECK(mxIsChar(mx) || mxIsFunctionHandle(mx),
"pre must contain function handles or function names");
if (mxIsChar(mx)) {
CHECK(mxGetString(mx, dpre.f, FLEN) == 0,
"error reading function name string (too long?)");
dpre.nrhs = 2;
dpre.xrhs = 0;
}
else {
dpre.prhs[0] = mx;
strcpy(dpre.f, "feval");
dpre.nrhs = 3;
dpre.xrhs = 1;
}
dpre.verbose = d.verbose > 2;
dpre.opt = opt;
dpre.neval = 0;
dpre.prhs[dpre.xrhs] = d.prhs[d.xrhs];
dpre.prhs[d.xrhs+1] = mxCreateDoubleMatrix(1, n, mxREAL);
d.dpre = &dpre;
if (struct_funcval(prhs[0], "min_objective"))
nlopt_set_precond_min_objective(opt, user_function,user_pre,&d);
else
nlopt_set_precond_max_objective(opt, user_function,user_pre,&d);
}
else {
dpre.nrhs = 0;
if (struct_funcval(prhs[0], "min_objective"))
nlopt_set_min_objective(opt, user_function, &d);
else
nlopt_set_max_objective(opt, user_function, &d);
}
if ((mx = mxGetField(prhs[0], 0, "fc"))) {
int j, m;
double *fc_tol;
CHECK(mxIsCell(mx), "fc must be a Cell array");
m = mxGetM(mx) * mxGetN(mx);;
dfc = (user_function_data *) mxCalloc(m, sizeof(user_function_data));
fc_tol = struct_arrval(prhs[0], "fc_tol", m, NULL);
for (j = 0; j < m; ++j) {
mxArray *fc = mxGetCell(mx, j);
CHECK(mxIsChar(fc) || mxIsFunctionHandle(fc),
"fc must contain function handles or function names");
if (mxIsChar(fc)) {
CHECK(mxGetString(fc, dfc[j].f, FLEN) == 0,
"error reading function name string (too long?)");
dfc[j].nrhs = 1;
dfc[j].xrhs = 0;
}
else {
dfc[j].prhs[0] = fc;
strcpy(dfc[j].f, "feval");
dfc[j].nrhs = 2;
dfc[j].xrhs = 1;
}
dfc[j].verbose = d.verbose > 1;
dfc[j].opt = opt;
dfc[j].neval = 0;
dfc[j].prhs[dfc[j].xrhs] = d.prhs[d.xrhs];
CHECK(nlopt_add_inequality_constraint(opt, user_function,
dfc + j,
fc_tol ? fc_tol[j] : 0)
> 0, "nlopt error adding inequality constraint");
}
}
if ((mx = mxGetField(prhs[0], 0, "h"))) {
int j, m;
double *h_tol;
CHECK(mxIsCell(mx), "h must be a Cell array");
m = mxGetM(mx) * mxGetN(mx);;
dh = (user_function_data *) mxCalloc(m, sizeof(user_function_data));
h_tol = struct_arrval(prhs[0], "h_tol", m, NULL);
for (j = 0; j < m; ++j) {
mxArray *h = mxGetCell(mx, j);
CHECK(mxIsChar(h) || mxIsFunctionHandle(h),
"h must contain function handles or function names");
if (mxIsChar(h)) {
CHECK(mxGetString(h, dh[j].f, FLEN) == 0,
"error reading function name string (too long?)");
dh[j].nrhs = 1;
dh[j].xrhs = 0;
}
else {
dh[j].prhs[0] = h;
strcpy(dh[j].f, "feval");
dh[j].nrhs = 2;
dh[j].xrhs = 1;
}
dh[j].verbose = d.verbose > 1;
dh[j].opt = opt;
dh[j].neval = 0;
dh[j].prhs[dh[j].xrhs] = d.prhs[d.xrhs];
CHECK(nlopt_add_equality_constraint(opt, user_function,
dh + j,
h_tol ? h_tol[j] : 0)
> 0, "nlopt error adding equality constraint");
}
}
x_mx = mxCreateDoubleMatrix(mxGetM(prhs[1]), mxGetN(prhs[1]), mxREAL);
x = mxGetPr(x_mx);
memcpy(x, x0, sizeof(double) * n);
ret = nlopt_optimize(opt, x, &opt_f);
mxFree(dh);
mxFree(dfc);
mxDestroyArray(d.prhs[d.xrhs]);
if (dpre.nrhs > 0) mxDestroyArray(dpre.prhs[d.xrhs+1]);
nlopt_destroy(opt);
plhs[0] = x_mx;
if (nlhs > 1) {
plhs[1] = mxCreateDoubleMatrix(1, 1, mxREAL);
*(mxGetPr(plhs[1])) = opt_f;
}
if (nlhs > 2) {
plhs[2] = mxCreateDoubleMatrix(1, 1, mxREAL);
*(mxGetPr(plhs[2])) = (int) ret;
}
}
When I write the following command :
mex nlopt_optimize.c
I get the following error messages
Error using mex
Cration de la bibliothque nlopt_optimize.lib et de l'objet nlopt_optimize.exp
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_create rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_destroy rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_optimize rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_min_objective rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_max_objective rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_precond_min_objective rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_precond_max_objective rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_lower_bounds rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_upper_bounds rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_add_inequality_constraint rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_add_equality_constraint rfrenc dans la fonction mexFunction
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_stopval rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_ftol_rel rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_ftol_abs rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_xtol_rel rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_xtol_abs rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_x_weights rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_maxeval rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_maxtime rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_force_stop rfrenc dans la fonction user_function
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_local_optimizer rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_population rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_vector_storage rfrenc dans la fonction make_opt
nlopt_optimize.obj : error LNK2019: symbole externe non rsolu nlopt_set_initial_step rfrenc dans la fonction make_opt
nlopt_optimize.mexw64 : fatal error LNK1120: 24 externes non rsolus
The errors are in french, the translation in english for the first error is for instance :
error LNK2019: unresolved external symbol nlopt_create referenced in function make_opt
I am really new to mex file compiling, my research on forums helped me to understand that the symbols are not avalable during the link-stage of the mex file compiling
My understanding ends here...
If any of you can help me on that, I would greatly appreciate. For you information, I am using Matlab 2022b
Thank you
2 Comments
Answers (1)
Jan
on 6 Dec 2022
I suggest to follow the official installation instructions: https://nlopt.readthedocs.io/en/latest/NLopt_Installation/ and for Windows: https://nlopt.readthedocs.io/en/latest/NLopt_on_Windows/ . In the 2nd link you find pre-compiled libaries.
4 Comments
Jan
on 8 Dec 2022
Okay. What a pity. This would be the point, at which I consider the project as "useful for insiders only". I've seen too many such projects, which runs fluently, if you know how to start it, but without useful instructions it is impossible to use for others.
Sigh. Sorry for my pessimistic estimation.
See Also
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!