3
$\begingroup$

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)
$\endgroup$
6
  • $\begingroup$ Did you try to compile the Wolfram example? Does it give the same error? $\endgroup$ Commented Nov 27, 2014 at 8:17
  • $\begingroup$ I compiled the supplied examples and they worked fine. $\endgroup$ Commented Nov 27, 2014 at 8:30
  • $\begingroup$ Ok, online doc says 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 has const char **headswhile I can see in a V8 a declaration using char **heads. One thing is for sure, one cannot cast char** to const char** $\endgroup$ Commented Nov 27, 2014 at 9:41
  • $\begingroup$ Stupid question, but did you try MLPutReal32Array(stdlink, (float *)gr, (int *)dim,(const char **)0, 2);? $\endgroup$ Commented Nov 27, 2014 at 9:46
  • $\begingroup$ Actually, gr and dim have the correct type, so MLPutReal32Array(stdlink,gr,dim,(const char**)0, 2); should be ok $\endgroup$ Commented Nov 27, 2014 at 9:51

1 Answer 1

6
$\begingroup$

It seems that the original type of (char **) (at least up to version 8) has been changed to (const char **). So try

MLPutReal32Array(stdlink,gr,dim,(const char**)0, 2);

with no need for a type cast on the second and third argument.

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.