[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


Hello

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
gsapi_init_with_args)


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 )

        -Sstdout=%stderr
        -dNOPAUSE
        -dBATCH
        -sOutputFile=%stdout
        -sDEVICE=pdfwrite
        -

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.


========================================================================
=====================================================
CODE:

Not yet commented, sorry


jgsAPIdll.c
------------------------------------------------------------------------
-----------------------------------------------------

/* 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
#endif
#ifdef _Windows
# include <windows.h>
# define GSDLLEXPORT __declspec(dllimport)
#endif
#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
status=_undefine_status(_status_instance_defined)
#define _unredirect_stdio
status=_undefine_status(_status_stdio_redirect)
#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,
methodsignature);
	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);
    	(*lenv)->GetByteArrayRegion(lenv,inarr,0,sz,buf);
	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);
	(*lenv)->SetByteArrayRegion(lenv,outarr,0,len,(byte*)str);
	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);
	(*lenv)->SetByteArrayRegion(lenv,errarr,0,len,(byte*)str);
	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",
"(Ljava/lang/String;Ljava/lang/String;II)V");
		(*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) {
		_define_instance;
	}

}

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

	_if_instance_defined {
		_undefine_instance;
		gsapi_delete_instance(minst);
	}

}

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

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

}

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",
"()[Ljava/lang/Object;");
	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 =
(jstring)(*env)->GetObjectArrayElement(env,joa,pos);
		pstr = (*env)->GetStringUTFChars(env,param,NULL);
		astr = strcpy((char*)malloc(strlen(pstr)+1),pstr);
		(char*)*(parr+pos+1) = astr;
		(*env)->ReleaseStringUTFChars(env,param,pstr);
	}
	gsapi_init_with_args(minst,len+1,parr);
	for (pos=1; pos<len+1; pos++) {
		free(*(parr+pos));
	}
	free(parr);

}

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

	gsapi_exit(minst);

}





More information about the gs-devel mailing list