diff --git a/modules/gmt/makemod b/modules/gmt/makemod new file mode 100644 index 0000000..94fc772 --- /dev/null +++ b/modules/gmt/makemod @@ -0,0 +1 @@ +MODLIBS+=-lgmt \ No newline at end of file diff --git a/modules/gmt/modgmt.cpp b/modules/gmt/modgmt.cpp new file mode 100644 index 0000000..98b07b0 --- /dev/null +++ b/modules/gmt/modgmt.cpp @@ -0,0 +1,86 @@ +#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; +} diff --git a/modules/gmt/modgmt.h b/modules/gmt/modgmt.h new file mode 100644 index 0000000..d2f3c00 --- /dev/null +++ b/modules/gmt/modgmt.h @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include "common.h" + +// Workaround exit() in GMT_Call_Module. May need because return mode of gmt api is not very reliable +#if defined MODGMT_WORKAROUND_EXIT +#define GMTMODE 0 +#else +#define GMTMODE 3 +#endif + +// here we save header and footer of gmt-produced eps files +std::string header,footer; + +// Parameters for working thread +struct gmtworkthreadpars +{ + void* api; + const char* module; + struct GMT_OPTION* opts; + int fd; + int ret; +}; + +extern "C" { +EXPORT int gmt_module_init(void* p); +} + +int callgmtmodule(void *api, const char *module, struct GMT_OPTION *opts, std::string& res); \ No newline at end of file