Re: Help in using gsapi_set_stdio() to capture stdout into a memory buffer
"Joaquim Luis" <[email protected]>
| Newsgroups | gmane.comp.printing.ghostscript.devel |
|---|---|
| Organization | UALG |
| Message-ID | <op.yety9icpdbaoe8@macmarilu> |
Hi again. I'm afraid I have to get back to this because I got stuck in a mystery. The attached code, sorry for the #ifdefs mess used for debugging, works when compiled as a standalone program (use the -DI_AM_MAIN pre-processor flag). It works only with small files where we can just do gs_rasterize ps_file.ps However, if I built it as a dll and send as argument the postscript code as a string, which will be called either from Matlab or Julia, than the call gsapi_run_string (GSinst, ps, 0, &GSexitCode) returns an error code GSexitCode = -12 I confirmed that the problem is not in the PS in memory with the code chunk under the #if 0. That is, that piece of code runs well from the stand-alone but fails when run from a dll. I'm completely clueless with this. Can it be because gs tries to do something that it has not right to do when controlled by another process (the one that calls the dll)? Thanks again Joaquim > At 16:17 17/03/2016 +0000, Joaquim Luis wrote: > > >> NOTE: the code file is attached, as it was in my first message. > > I'm afraid (for me) your email ended up in a Google spam folder and I > had to dig it out manually. Somewhere in there the code obviously fell > off, apologies for that. > > > Ken _______________________________________________ gs-devel mailing list [email protected] http://ghostscript.com/cgi-bin/mailman/listinfo/gs-devel
gs_rasterize.c
(application/octet-stream, 7.2 KB)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#ifdef _WIN32
# include "ierrors.h"
# include "iapi.h"
# include <process.h>
# include <io.h>
# define dup2 _dup2
# define fileno _fileno
# define close _close
# define stat _stat
#else
# include "ghostscript/ierrors.h"
# include "ghostscript/iapi.h"
# include <unistd.h>
#endif
# ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBSPEC __declspec(dllimport)
# else
# define LIBSPEC __declspec(dllexport)
# endif /* ifdef LIBRARY_EXPORTS */
# else /* ifdef _WIN32 */
# define LIBSPEC
# endif /* ifdef _WIN32 */
/* By default, we use the standard "extern" declarations. */
# define EXTERN_MSC_ extern LIBSPEC
#ifndef I_AM_MAIN
EXTERN_MSC_ unsigned char *gsrasterize_rip (char *ps, int dpi, int dim[]);
EXTERN_MSC_ void gsrasterize_free (char *img);
#endif
char *ps_test = "newpath\n"
"100 600 moveto 200 650 lineto 100 700 lineto\n"
"closepath\n"
"gsave\n"
"0.5 setgray\n"
"fill\n"
"grestore\n"
"4 setlinewidth\n"
"stroke\n"
"/Times-Roman findfont\n"
"18 scalefont\n"
"setfont\n"
"newpath\n"
"150 600 moveto\n"
"(Julia-Ghostscript in action) show\n"
"/csquare {\n"
"newpath\n"
"0 26 moveto\n"
"0 1 rlineto\n"
"1 0 rlineto\n"
"0 -1 rlineto\n"
"closepath\n"
"setrgbcolor\n"
"fill\n"
"} def\n"
"\n"
"20 20 scale\n"
"\n"
"1 5 translate\n"
"1 0 0 csquare\n"
"\n"
"1 0 translate\n"
"0 1 0 csquare\n"
"\n"
"1 0 translate\n"
"0 0 1 csquare\n"
"showpage";
void gsrasterize_free (char *img) {
/* Free memory allocated in this file. Needed because the cross boundary dll on Windows */
if (img) free (img);
}
/* stdio functions */
static int GSDLLCALL gsdll_stdin (void *instance, char *buf, int len) {
return 0;
}
static int GSDLLCALL gsdll_stdout (void *instance, const char *str, int len) {
//fwrite(str, 1, len, fp);
//fflush(fp);
return len;
}
static int GSDLLCALL gsdll_stderr (void *instance, const char *str, int len) {
fwrite (str, 1, len, stderr);
fflush (stderr);
return len;
}
#define ROWS 0
#define COLS 1
#define BANDS 2
/* The I_AM_MAIN brach is initially intended as a dev/debug feature, where we can build this
as a stand alone program and send for example a PS file name.
*/
#ifdef I_AM_MAIN
int main (int argc, char *argv[]) {
int dpi = 300;
int dim[3]; /* Not meant to be used for now */
int arg_c = argc;
char *ps = NULL;
#else
unsigned char *gsrasterize_rip (char *ps, int dpi, int dim[]) {
int arg_c = 0;
#endif
int GScode = 0, GSexitCode, n, fd[2] = {0, 0};
size_t size;
char buf[1025], t[16] = {""}, s_dpi[16] = {"-r300x300"}, *ps_t;
unsigned char *img = NULL;
void *GSinst = NULL;
FILE *fp = NULL;
char *GSargs[] = { /* Presumably need to specify dpi at some point */
"", "-sDEVICE=ppmraw", "-dBATCH", "-dNOPAUSE", "-sOutputFile=-", "-q", NULL
};
char line[BUFSIZ];
struct stat F;
#ifdef I_AM_MAIN
//char line[BUFSIZ];
//struct stat F;
if (arg_c > 1) {
stat (argv[1], &F);
if ((fp = fopen (argv[1], "r")) == NULL) {
fprintf(stderr, "Error reading PS %s file. Bye bye\n", argv[1]);
return -1;
}
fprintf (stderr, "PS file size is %d bytes\n", (int)F.st_size);
ps = (char *)calloc(F.st_size+1, sizeof(char));
while (fgets (line, BUFSIZ, fp))
strcat(ps, line);
}
else {
ps = ps_test;
}
#endif
if (dpi > 0) sprintf (s_dpi, "-r%dx%d", dpi, dpi); else sprintf (s_dpi, "-r300x300");
GSargs[6] = s_dpi;
if ((GScode = gsapi_new_instance (&GSinst, NULL )) < 0 ) {
fprintf (stderr, "Error: GhostScript gsapi_new_instance failed (error code %d)\n", GScode);
#ifdef I_AM_MAIN
if (arg_c > 1) free (ps);
return -1;
#else
return NULL;
#endif
}
gsapi_set_stdio (GSinst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
if ((GScode = gsapi_init_with_args (GSinst, 6, GSargs)) < 0 ) {
fprintf (stderr, "Error: GhostScript gsapi_init_with_args failed (error code %d)\n", GScode);
gsapi_exit (GSinst);
gsapi_delete_instance (GSinst);
#ifdef I_AM_MAIN
if (arg_c > 1) free (ps);
return -1;
#else
return NULL;
#endif
}
/* Establish a pipe to read from stdout */
#ifdef _WIN32
if (_pipe(fd, 145227600, O_BINARY) == -1) {
fprintf(stderr, "Error: failed to open the pipe\n");
gsapi_exit(GSinst);
gsapi_delete_instance(GSinst);
if (arg_c > 1) free(ps);
return -1;
}
#else
pipe (fd);
#endif
if (dup2 (fd[1], fileno (stdout)) < 0) { /* Failed to duplicate pipe */
fprintf (stderr, "Error: Failed to duplicate pipe\n");
gsapi_exit (GSinst);
gsapi_delete_instance (GSinst);
#ifdef I_AM_MAIN
if (arg_c > 1) free (ps);
return -1;
#else
return NULL;
#endif
}
close (fd[1]); /* Close original write end of pipe */
#if 0
stat ("V:\\lili.ps", &F);
if ((fp = fopen ("V:\\lili.ps", "r")) == NULL) {
fprintf(stderr, "Error reading PS %s file. Bye bye\n", "V:\\lili.ps");
return -1;
}
ps_t = (char *)calloc(F.st_size+1, sizeof(char));
while (fgets (line, BUFSIZ, fp))
strcat(ps_t, line);
if (gsapi_run_string (GSinst, ps_t, 0, &GSexitCode) < 0)
fprintf (stderr, "Error: GhostScript gsapi_run_string failed (error code %d)\n", GSexitCode);
free (ps_t);
#endif
if ((n = gsapi_run_string (GSinst, ps, 0, &GSexitCode)) < 0) {
fprintf (stderr, "Error: GhostScript gsapi_run_string failed (error code %d\t%d)\n", GSexitCode, n);
gsapi_exit (GSinst);
gsapi_delete_instance (GSinst);
#ifdef I_AM_MAIN
if (arg_c > 1) free (ps);
return -1;
#else
return NULL;
#endif
}
/* Successful so far so let us read the raw pbm image into memory */
n = read (fd[0], buf, 3U); /* Consume first header line */
while (read (fd[0], buf, 1U) && buf[0] != '\n') /* OK, by the end of this we are at the end of second header line */
fprintf(stderr, "%c", buf[0]);
n = 0;
while (read(fd[0], buf, 1U) && buf[0] != ' ') /* Get string with number of columns from 3rd header line */
t[n++] = buf[0];
dim[COLS] = atoi (t);
n = 0;
while (read(fd[0], buf, 1U) && buf[0] != '\n') /* Get string with number of rows from 3rd header line */
t[n++] = buf[0];
t[n] = '\0'; /* Make sure no character is left from previous usage */
while (read(fd[0], buf, 1U) && buf[0] != '\n') /* Consume fourth header line */
fprintf(stderr, "%c", buf[0]);
dim[ROWS] = atoi (t);
dim[BANDS] = 3; /* This might change if we do monochrome at some point */
size = dim[ROWS] * dim[COLS] * dim[BANDS]; /* Determine number of bytes needed to hold image */
if ((img = malloc (size)) == NULL) {
fprintf (stderr, "Error: Unable to allocate space for image [%d bytes]\n", (int)size);
gsapi_exit (GSinst);
gsapi_delete_instance (GSinst);
#ifdef I_AM_MAIN
if (arg_c > 1) free (ps);
return -1;
#else
return NULL;
#endif
}
/* Read the image */
if ((n = read (fd[0], img, size)) >= 0) {
fprintf (stderr, "read %d bytes from the pipe:\n %s\n", n, buf);
}
else
perror ("read");
/* Clean up and return image */
gsapi_exit (GSinst);
gsapi_delete_instance (GSinst);
#ifdef I_AM_MAIN
if (arg_c > 1) free (ps);
n = write(fileno(stdout), img, size);
fprintf(stderr, "wrote %d bytes to stdout\n", n);
gsrasterize_free (img);
return 0;
#else
return img;
#endif
}