I have some c++ code I wrote in Windows that compiles and runs just fine. I was going to use it on a Linux machine but I am getting the error when I try to compile following the Makefile procedure outlined in the Mathematica documentation.
error: invalid conversion from ‘char**’ to ‘const char**’ [-fpermissive]
MLPutReal32Array(stdlink, (float *)gr, (int *)dim,(char **)0, 2);
^
In file included from twositetwochaindimer.cpp:12:0:
mathlink.h:6013:16: error: initializing argument 4 of ‘int MLPutReal32Array(MLINK, const float*, const int*, const char**, int)’ [-fpermissive]
MLDECL( int, MLPutReal32Array, ( MLINK mlp, const float * data, const int *dims, const char **heads, int depth));
^
mathlink.h:864:57: note: in definition of macro ‘MLDECL’
#define MLDECL( rtype, name, params) extern rtype MLAPI name P(params)
^
make: *** [twositetwochaindimer.o] Error 1
I am using Mathematica 10 (I have tried this using both the Mathlink libraries and the new Wolfram Symbolic Transfer Protocol (WSTP) and get the same error.
Here is my code, *.tm file and Makefile for reference.
#include <iostream>
#include <cmath>
#include <random>
#include <cstdlib>
#include <ctime>
#include <new>
using namespace std;
#include "mathlink.h"
extern void mchshdpre6linux(float *wr0, int wr0len, float *wr1, int wr1len, float *wr2, int wr2len, float *plist, int plistlen, float solFactor, int poplen, int vectlen, int seed, int mcmax, int start, int stop);
extern void randomsphere(float c[3], float r);
extern int round_int(float r);
extern int int_IntRange(int a, int b);
void randomonsphere(float c[3], float r)
{
float pi = 3.14159265;
float theta = ((float)rand() / (float)RAND_MAX) * 2 * pi;
float u = 2 * ((float)rand() / (float)RAND_MAX) - 1;
c[0] = r*cos(theta)*sqrt(1.0 - u*u);
c[1] = r*sin(theta)*sqrt(1.0 - u*u);
c[2] = r*u ;
}
int round_int(float r)
{
return (r > 0.0) ? (r + 0.5) : (r - 0.5);
}
int rand_IntRange(int a, int b)
{
return rand() % (b - a + 1) + a;
}
void mchshdpre6linux(float *wr0, int wr0len, float *wr1, int wr1len, float *wr2, int wr2len, float *plist, int plistlen, float solFactor, int poplen, int vectlen, int seed, int mcmax, int start, int stop)
{
/* This is the intial configuration for the two chains*/
float sigmaa = plist[0];
float sigmab = plist[1];
float bl = plist[2];
float t = plist[3];
//float bl = 3.93;
//float t =42.6
//float sigma = 3.93;
float chain[4][3] = { { bl, 0.0, 1.0 }, { 0.0, 0.0, 0.0 }, { bl, 0.0, 0.0 }, { 0.0, 0.0, 0.0 } };
float delr = 0.1;
int ngrid = 2048;
int temp[2][2] = { { 0, 0 }, { 0, 0 } };
float sphere = 1.0;
int rmin = start;
int rmax = stop;
float sr;
float x1[3] = { 0., 0., 0. };
float x2[3] = { 0., 0., 0. };
float dir[3] = { 0., 0., 0. };
float vr[3];
float dis[3];
float energy;
int rIndex;
float rFactor;
float solE;
float ljE;
float gr[2048][3] = { 0.0, 0.0, 0.0 };
float kb = 0.0019833794749;
float entemp = 0.0;
int dim[2];
dim[0] = 2048;
dim[1] = 3;
//float hr[2048] = { 0 };
float sigma[2][2]={ { 0, 0 }, { 0, 0 } };
int choice1;
int choice2;
int choice3;
float sited[3];
sigma[0][0] = 0.5*(sigmaa + sigmaa);
sigma[0][1] = 0.5*(sigmaa + sigmab);
sigma[1][0] = 0.5*(sigmab + sigmaa);
sigma[1][1] = 0.5*(sigmab + sigmab);
srand(seed);
//const int numrows = poplen;
int numcols = 3;
//generate new array for vectors
float **vectorlist = new float*[vectlen];
for (int i = 0; i < vectlen; ++i)
{
vectorlist[i] = new float[3];
}
//generate new array orientations of dimers
float **chainpop = new float*[poplen];
for (int i = 0; i < poplen; ++i)
{
chainpop[i] = new float[3];
}
for (int p = 0; p < poplen; p++)
{
randomonsphere(sited, bl);
for (int c = 0; c < numcols; c++)
{
chainpop[p][c] = sited[c];
}
}
for (int p = 0; p < vectlen; p++)
{
randomonsphere(sited, 1);
for (int c = 0; c < numcols; c++)
{
vectorlist[p][c] = sited[c];
}
}
for (int i = 1; i <= mcmax; i++)
{
for (int n = rmin; n <= rmax; n++)
{
for (int j = 0; j <= 1; j++)
{
for (int k = 0; k <= 1; k++)
{
temp[k][j] = 0.0;
}
}
/*randomonsphere(x1, bl);
randomonsphere(x2, bl);*/
choice1 = rand_IntRange(0, poplen-1);
choice2 = rand_IntRange(0, poplen-1);
choice3 = rand_IntRange(0, vectlen - 1);
for (int q = 0; q < 3;q++)
{
x1[q] = chainpop[choice1][q];
x2[q] = chainpop[choice2][q];
dis[q] = vectorlist[choice3][q]*delr*n;
}
solE = 0.0;
ljE = 0.0;
int da = rand() % 2;
int db = rand() % 2;
if (da == 1)
{
for (int j = 0; j <= 2; j++)
{
chain[0][j] = 0.0;
chain[1][j] = x1[j];
}
}
else if (da == 0)
{
for (int j = 0; j <= 2; j++)
{
chain[1][j] = 0.0;
chain[0][j] = x1[j];
}
}
if (db == 1)
{
for (int j = 0; j <= 2; j++)
{
chain[2][j] = 0.0;
chain[3][j] = x2[j];
}
}
else if (db ==0)
{
for (int j = 0; j <= 2; j++)
{
chain[3][j] = 0.0;
chain[2][j] = x2[j];
}
}
/*dis[0] = dir[0]*delr*n;
dis[1] = dir[1]*delr*n;
dis[2] = dir[2]*delr*n;*/
energy = 0.0;
for (int j = 0; j <= 1; j++)
{
for (int k = 0; k <= 1; k++)
{
for (int s = 0; s <= 2; s++)
{
vr[s] = chain[k + 2][s] - chain[j][s] + dis[s];
sr = 0.0;
}
for (int s = 0; s <= 2; s++)
{
sr = vr[s] * vr[s] + sr;
}
sr = sqrt(sr);
temp[j][k] = round_int(sr / delr) - 1;
rIndex = round_int(sr / delr) - 1;
rFactor = sr / delr - rIndex - 1;
if (rIndex == 0)
{
if (j == 0 && k == 0){
solE = solE + solFactor*wr0[0];
}
else if (j == 0 && k == 1){
solE = solE + solFactor*wr1[0];
}
else if (j == 1 && k == 0){
solE = solE + solFactor*wr1[0];
}
else if (j == 1 && k == 1){
solE = solE + solFactor*wr2[0];
}
}
else if (rIndex < wr0len)
{
if (j == 0 && k == 0)
{
solE = solE + solFactor*(wr0[rIndex] * (1.0 - rFactor) + rFactor*wr0[rIndex + 1]);
}
else if (j == 0 && k == 1)
{
solE = solE + solFactor*(wr1[rIndex] * (1.0 - rFactor) + rFactor*wr1[rIndex + 1]);
}
else if (j == 1 && k == 0)
{
solE = solE + solFactor*(wr1[rIndex] * (1.0 - rFactor) + rFactor*wr1[rIndex + 1]);
}
else if (j == 1 && k == 1)
{
solE = solE + solFactor*(wr2[rIndex] * (1.0 - rFactor) + rFactor*wr2[rIndex + 1]);
}
}
//if (sr*sr >= sigma*sigma)
if (sr*sr >= sigma[j][k]*sigma[j][k])
{
entemp = 0.0;
}
else
{
entemp = 1000000000.0;
}
energy = energy + entemp;
}
}
for (int j = 0; j <= 1; j++)
{
for (int k = 0; k <= 1; k++)
{
if (j == 0 && k == 0){
gr[temp[j][k]][0] = gr[temp[j][k]][0] + exp(-(energy + solE) / (kb*t))*n*n;
}
else if (j == 0 && k == 1){
gr[temp[j][k]][1] = gr[temp[j][k]][1] + exp(-(energy + solE) / (kb*t))*n*n;
}
else if (j == 1 && k == 0){
gr[temp[j][k]][1] = gr[temp[j][k]][1] + exp(-(energy + solE) / (kb*t))*n*n;
}
else if (j == 1 && k == 1){
gr[temp[j][k]][2] = gr[temp[j][k]][2] + exp(-(energy + solE) / (kb*t))*n*n;
}
}
}
}
}
// free dynamic memory
for(int i = 0; i < vectlen; i++)
{
delete[] vectorlist[i];
}
for(int i = 0; i < poplen; i++)
{
delete[] chainpop[i];
}
delete[] vectorlist;
delete[] chainpop;
MLPutReal32Array(stdlink, (float *)gr, (int *)dim,(char **)0, 2);
return;
}
#if WINDOWS_MATHLINK
#if __BORLANDC__
#pragma argsused
#endif
int PASCAL WinMain( HINSTANCE hinstCurrent, HINSTANCE hinstPrevious, LPSTR lpszCmdLine, int nCmdShow)
{
char buff[512];
char FAR * buff_start = buff;
char FAR * argv[32];
char FAR * FAR * argv_end = argv + 32;
hinstPrevious = hinstPrevious; /* suppress warning */
if( !MLInitializeIcon( hinstCurrent, nCmdShow)) return 1;
MLScanString( argv, &argv_end, &lpszCmdLine, &buff_start);
return MLMain( (int)(argv_end - argv), argv);
}
#else
int main(int argc, char* argv[])
{
return MLMain(argc, argv);
}
#endif
*.tm file
:Begin:
:Function: mchshdpre6linux
:Pattern: mchshdpre6linux[a1_List, a2_List, a3_List, p1_List, b_Real, c_Integer, d_Integer, e_Integer, f_Integer, g_Integer, h_Integer]
:Arguments: {a1, a2, a3, p1, b, c, d, e, f, g, h}
:ArgumentTypes: {Real32List, Real32List, Real32List, Real32List, Real32, Integer, Integer, Integer, Integer, Integer, Integer}
:ReturnType: Manual
:End:
and Makefile
# This makefile can be used to build all or some of the sample
# programs. To build all of them, use the command
# 'make all'. To build one, say addtwo, use the command
# 'make addtwo'.
# Portions of this makefile require the use of GNU make.
# see http://www.gnu.org/software/make for more information.
VERSION=10.0
MLINKDIR = $(shell pwd)/..
SYS = Linux-x86-64
CADDSDIR = $//usr/local/Wolfram/Mathematica/10.0/SystemFiles/Links/MathLink/DeveloperKit/Linux-x86-64/CompilerAdditions
EXTRA_CFLAGS=-m64
CXXFLAGS =-std=c++0x
INCDIR = ${CADDSDIR}
LIBDIR = ${CADDSDIR}
MPREP = ${CADDSDIR}/mprep
RM = rm
CC = /usr/bin/cc
CXX = /usr/bin/c++
BINARIES = mchshdpre6linux
all : $(BINARIES)
mchshdpre6linux : twositetwochaindimertm.o twositetwochaindimer.o
${CXX} ${CXXFLAGS} ${EXTRA_CFLAGS} -I${INCDIR} twositetwochaindimertm.o twositetwochaindimer.o -L${LIBDIR} -lML64i4 -lm -lpthread -lrt -lstdc++ -ldl -luuid -o $@
.c.o :
${CC} -c ${EXTRA_CFLAGS} -I${INCDIR} $<
twositetwochaindimertm.c : twositetwochaindimer.tm
${MPREP} $? -o $@
clean :
@ ${RM} -rf *.o *tm.c $(BINARIES)
int MLPutReal32Array(MLINK link,float *a,int *dims,char **heads, int d)
and the online example uses(char **)0
. Maybe that is an older version, as this mathlink.h hasconst char **heads
while I can see in a V8 a declaration usingchar **heads
. One thing is for sure, one cannot castchar**
toconst char**
$\endgroup$MLPutReal32Array(stdlink, (float *)gr, (int *)dim,(const char **)0, 2);
? $\endgroup$MLPutReal32Array(stdlink,gr,dim,(const char**)0, 2);
should be ok $\endgroup$