API for makecpt

Hello,
I am trying to use the GMT API to develop some external tools. When I want to get the coast lines, these simple instructions work like a charm:

API = GMT_Create_Session(“GMT_coast”, 2, 0, NULL);
GMT_Open_VirtualFile(API, GMT_IS_DATASET, GMT_IS_PLP, GMT_OUT, NULL, output);
GMT_Call_Module(API, “coast”, argc, argv);
D = GMT_Read_VirtualFile(API, output);

I get exactly what I need in the dataset structure D.

But when I want to get palette colors, this way:

API = GMT_Create_Session(“GMT_makecpt”, 2, 0, NULL);
GMT_Open_VirtualFile(API, GMT_IS_PALETTE, GMT_IS_NONE, GMT_OUT, NULL, output);
GMT_Call_Module(API, “makecpt”, argc, argv);
P = GMT_Read_VirtualFile(API, output);

I cannot even reach the last line, the call to makecpt aborts into gmtlib_copy_palette. Therefore, it seems like I must allocate the palette structure before calling the module, while it was not needed for coast.

Can anybody confirm this? And is there a mean to decide if I have to allocate memory first or not? Is there best practices?
Thanks, regards,

Olivier

Hi Olivier-

I can try this but I do not know what your command line arguments are. Presumably the ones you pass to coast are different than what you pass to makecpt, so I worry that is where the problem lies.

Hi Paul,

thank you for your reply. Here is what I passed to coast first:
argv = {"-Jx1d", “-R-180/180/-90/90”, “-Dc”, “-M”, “-W”}
and to makecpt:
argv = {"-Ccool", “-T1/65/1”, “-N”}
Furthermore, I checked that calling makecpt from the command line with these arguments works perfectly.

Perhaps you are running an old version of GMT. I am working with master from GitHub (so what will become 6.2.0). This worked for me:

int main () {
	char output[GMT_VF_LEN] = {""};
	char *arg[3] = {"-Ccool", "-T1/65/1", "-N"};
	void *P = NULL, *API = GMT_Create_Session ("GMT_makecpt", 2, 0, NULL);
	GMT_Open_VirtualFile (API, GMT_IS_PALETTE, GMT_IS_NONE, GMT_OUT, NULL, output);
	GMT_Call_Module (API, "makecpt", 3, arg);
	P = GMT_Read_VirtualFile(API, output);
}
cc olivier.c $(gmt-config --cflags) $(gmt-config --libs) -o olivier
./olivier
1 1.9922/253.01/255 2 1.9922/253.01/255 L
2 5.9766/249.02/255 3 5.9766/249.02/255 L
3 9.9609/245.04/255 4 9.9609/245.04/255 L

Your code runs perfectly here too.
The problem arises when I try to add "->"output as a last argument (see below, sorry for all the missing stars, I don’t know how to show code). It’s mandatory if I want the output in memory and not on stdout, isn’t it?

#include <stdio.h>
#include <string.h>
#include “gmt.h”

int main () {
char output[GMT_VF_LEN] = {""};
char arg = (char) malloc(4 * sizeof(char*));
struct GMT_PALETTE P = NULL;
void API = GMT_Create_Session (“GMT_makecpt”, 2, 0, NULL);
GMT_Open_VirtualFile (API, GMT_IS_PALETTE, GMT_IS_NONE, GMT_OUT, NULL, output);
arg[0] = (char
) calloc(7, sizeof(char));
sprintf(arg[0], “-Ccool”);
arg[1] = (char
) calloc(9, sizeof(char));
sprintf(arg[1], “-T1/65/1”);
arg[2] = (char*) calloc(3, sizeof(char));
sprintf(arg[2], “-N”);
arg[3] = (char*) calloc(strlen(output)+3, sizeof(char));
sprintf(arg[3], “->%s”, output);
GMT_Call_Module (API, “makecpt”, 4, arg);
P = GMT_Read_VirtualFile(API, output);
}

gcc olivier.c -g $(gmt-config --cflags) $(gmt-config --libs) -o olivier

valgrind -v ./olivier

==17831== Invalid write of size 8
==17831== at 0x4F2BBFC: gmtlib_copy_palette (in /usr/local/gmt/gmt-6.1.1/lib/libgmt.so.6.1.1)
==17831== by 0x4EA077E: GMT_Write_Data (in /usr/local/gmt/gmt-6.1.1/lib/libgmt.so.6.1.1)
==17831== by 0x5140640: GMT_makecpt (in /usr/local/gmt/gmt-6.1.1/lib/libgmt.so.6.1.1)
==17831== by 0x4E8A665: GMT_Call_Module (in /usr/local/gmt/gmt-6.1.1/lib/libgmt.so.6.1.1)
==17831== by 0x108B33: main (olivier.c:19)
==17831== Address 0x0 is not stack’d, malloc’d or (recently) free’d

Sorry, I forgot about that - you want it back into P. Yes I get the crash too. So I will debug and report back with a fix.

I have fixed the bug and added a test based on your code so we should be covered. The PR has beem merged into master, i.e., see here

Thank you very much, Paul! I am going to get the head of master to run my code.
Regards,
Olivier