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$
  • $\begingroup$ Did you try to compile the Wolfram example? Does it give the same error? $\endgroup$ – mikuszefski Nov 27 '14 at 8:17
  • $\begingroup$ I compiled the supplied examples and they worked fine. $\endgroup$ – user573214 Nov 27 '14 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$ – mikuszefski Nov 27 '14 at 9:41
  • $\begingroup$ Stupid question, but did you try MLPutReal32Array(stdlink, (float *)gr, (int *)dim,(const char **)0, 2);? $\endgroup$ – mikuszefski Nov 27 '14 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$ – mikuszefski Nov 27 '14 at 9:51
5
$\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$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.