[gs-devel] Problem with callback functions in API (without header file because otherwise >12kb)

cpoisel at exago.de cpoisel at exago.de
Fri Jun 18 02:41:54 PDT 2004


At the moment i'm  writing a Document Management Solution that should
integrate with an existing VB6 Application. As I don't like to do work
twice I decided to write this new Software as a servlet based on Java &
Tomcat so that it can be used across multiple platforms. To make it
possible to import data that is output on a printer I started to write a
virtual network printer that should be able to accept Postscript
printjobs  and convert it to several formats (the most important one is
PDF). I decided to use Ghostscript as the backend for file conversion
and wrote an interface class and shared library to get the input from a
java DataInputStream into Ghostscript and back into a DataOutputStream.
I use the gsapi_set_stdio call to redirect stdin, stdout and stderr.
Everything works fine now except one thing: I don't get the PDF output
redirected to my stdout function and so i don't get it back into java.
The redirection routines work (I was able to write the following to
stdout and stderr function depending on the parameters chosen in

AFPL Ghostscript 8.14 (2004-02-20)
Copyright (C) 2004 artofcode LLC, Benicia, CA.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
Loading NimbusRomNo9L-Regu font from C:\gs\fonts/n021003l.pfb... 2368360
978610 1557192 268445 3 done.

At the moment I use the following parameters  (but i also have already
used every spelling possible for redirecting stdio )


The result is: 	AFPL Ghostscript 8.14 ... is written to a file connected
to stderr via JAVA	that's correct
		The file connected to stdout via JAVA is empty (0 bytes
long)				that's where i expected the output file
		The pdf output is written to the console I started the
application from.

I'm able to create a PDF output-file with the following command:
java gsAPIwrap >out.pdf

I have absolutely no idea what to do to get the PDF output redirected to
my stdout redirection function.


Not yet commented, sorry


/* Include JNI Header File */
#include "gsAPIwrap.h"

/* Include System Header Files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Include Ghostscript Header Files and neccessary System Header Files
#if defined(_WIN32) && !defined(_Windows)
# define _Windows
#ifdef _Windows
# include <windows.h>
# define GSDLLEXPORT __declspec(dllimport)
#include <iapi.h>
#include <ierrors.h>

int status = 0;

#define _status_instance_defined	1
#define _status_stdio_redirect		2
#define _define_status(mask) status=status&mask
#define _undefine_status(mask) status=status&~mask
#define _if_defined(mask) if((status & mask)>0) 
#define _define_instance status=_define_status(_status_instance_defined)
#define _redirect_stdio status=_define_status(_status_stdio_redirect)
#define _undefine_instance
#define _unredirect_stdio
#define _if_instance_defined _if_defined(_status_instance_defined)
#define _if_stdio_redirected _if_defined(_status_stdio_redirect)

gs_main_instance *minst;
JNIEnv *lenv;
jobject lobj;

jmethodID getMethodID(JNIEnv *env, jobject obj, char *methodname, char
*methodsignature) {

	jclass cls;
	jmethodID mid;

	cls = (*env)->GetObjectClass(env, obj);
    	mid = (*env)->GetMethodID(env, cls, methodname,
	return mid;


static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len) {

	jmethodID mid;
	jbyteArray inarr;
	jsize sz;
	inarr = (*lenv)->NewByteArray(lenv,len);
	mid = getMethodID(lenv, lobj, "gsSTDIN", "([BI)I");
	sz = (*lenv)->CallIntMethod(lenv, lobj, mid, inarr, len);
	return sz;


static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int
len) {

	jmethodID mid;
	jbyteArray outarr;
	jsize sz;

	outarr = (*lenv)->NewByteArray(lenv,len);
	mid = getMethodID(lenv, lobj, "gsSTDOUT", "([BI)I");
	sz = (*lenv)->CallIntMethod(lenv, lobj, mid, outarr, len);
	printf("stdout called: %s\n", str);
	return sz;


static int GSDLLCALL gsdll_stderr(void *instance, const char *str, int
len) {

	jmethodID mid;
	jbyteArray errarr;
	jsize sz;

	errarr = (*lenv)->NewByteArray(lenv,len);
	mid = getMethodID(lenv, lobj, "gsSTDERR", "([BI)I");
	sz = (*lenv)->CallIntMethod(lenv, lobj, mid, errarr, len);
	return sz;


JNIEXPORT void JNICALL Java_gsAPIwrap_jgsRevision (JNIEnv *env, jobject
obj) {

	jstring product, copyright;
	jint revision, revdate;
	jmethodID mid;
	gsapi_revision_t r;	

	if (gsapi_revision(&r, sizeof(r))==0) {
		product = (*env)->NewStringUTF(env, r.product);
		copyright = (*env)->NewStringUTF(env, r.copyright);
		revision = r.revision;
		revdate = r.revisiondate;
                      	mid = getMethodID(env, obj, "gsInitSuccess",
		(*env)->CallVoidMethod(env, obj, mid, product,
copyright, revision, revdate);


JNIEXPORT void JNICALL Java_gsAPIwrap_jgsNewInstance(JNIEnv *env,
jobject obj) {

/*	jmethodID mid;*/
	if (gsapi_new_instance(&minst, NULL)<0) {


JNIEXPORT void JNICALL Java_gsAPIwrap_jgsDeleteInstance(JNIEnv *env,
jobject obj) {

	_if_instance_defined {


JNIEXPORT void JNICALL Java_gsAPIwrap_jgsSetStdio(JNIEnv *env, jobject
obj) {

	_if_stdio_redirected {
	gsapi_set_stdio(minst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
	lobj = (*env)->NewGlobalRef(env,obj);
	lenv = env;


JNIEXPORT void JNICALL Java_gsAPIwrap_jgsInitWithArgs(JNIEnv *env,
jobject obj) {
	jmethodID mid;
	jobjectArray joa;
	jsize len, pos;
	jstring param;
	const char *pstr;
	char *astr;
	char **parr;

            mid = getMethodID(env, obj, "getParameters",
	joa = (jarray)(*env)->CallObjectMethod(env, obj, mid);
	len = (*env)->GetArrayLength(env,joa);
	parr=(char**) calloc(len+1,sizeof(char*));
	(char*)*parr = "JAVA 2 Ghostscript Interface";
	for (pos=0; pos<len; pos++) {
		param =
		pstr = (*env)->GetStringUTFChars(env,param,NULL);
		astr = strcpy((char*)malloc(strlen(pstr)+1),pstr);
		(char*)*(parr+pos+1) = astr;
	for (pos=1; pos<len+1; pos++) {


JNIEXPORT void JNICALL Java_gsAPIwrap_jgsExit(JNIEnv *env, jobject obj)



More information about the gs-devel mailing list