#include "modgmt.h" #if defined MODGMT_WORKAROUND_EXIT // Exit handler. static void gmtonexithandler(int ret, void* x) { reinterpret_cast(x)->ret=ret; close(reinterpret_cast(x)->fd); pthread_exit(&(reinterpret_cast(x)->ret)); } #endif // This function call GMT_Call_Module in separate thread. It just a hack to workaround absence of callbacks. static void* gmtworkthread(void* x) { struct gmtworkthreadpars* p=reinterpret_cast(x); #if defined MODGMT_WORKAROUND_EXIT on_exit(gmtonexithandler,x); #endif GMT_Append_Option(p->api,GMT_Make_Option(p->api,'>',const_cast(("/dev/fd/"+std::to_string(p->fd)).c_str())),p->opts); p->ret=GMT_Call_Module(p->api,p->module,GMT_MODULE_OPT,p->opts); #if defined MODGMT_WORKAROUND_EXIT exit(p->ret); #endif close(p->fd); return &p->ret; } // Wrapper for GMT_Call_Module, res is output. int callgmtmodule(void *api, const char *module, struct GMT_OPTION *opts, std::string& res) { int pipefd[2]; ssize_t br; char buffer[4096]; pthread_t wthr; struct gmtworkthreadpars p; int *pret; pipe(pipefd); p.api=api; p.module=module; p.opts=opts; p.fd=pipefd[1]; pthread_create(&wthr,0,&gmtworkthread,&p); res.erase(); do { br=read(pipefd[0],buffer,4096); res.append(buffer,br); } while(0!=br); close(pipefd[0]); res.shrink_to_fit(); pthread_join(wthr,reinterpret_cast(&pret)); return *pret; } // Initialisation function int gmt_module_init(void* p) { // Fill header and footer struct GMT_OPTION* opts; void* gmtapi; int ret; const char* ch="--GMT_HISTORY=f -C -P -K"; const char* cf="--GMT_HISTORY=f -C -P -O"; char* h=strdup(ch); char* f=strdup(cf); gmtapi=GMT_Create_Session("gmt_makemap",2,3,0); if(0==gmtapi) return 1; opts=GMT_Create_Options(gmtapi,0,h); ret=callgmtmodule(gmtapi,"psclip",opts,header); GMT_Destroy_Options(gmtapi,&opts); opts=GMT_Create_Options(gmtapi,0,f); if(0==ret) ret=callgmtmodule(gmtapi,"psclip",opts,footer); GMT_Destroy_Options(gmtapi,&opts); GMT_Destroy_Session(gmtapi); free(h); free(f); if(0!=ret) return ret; return 0; }