[Ecls-list] new ECL list member/ ECL project
Goffioul Michael
goffioul at imec.be
Wed Jan 25 01:20:01 UTC 2006
> Hi Michael,
>
> Thanks for that. My app doesn't crash now.
> How do you setup a gray stream ?
>
> I'd love to be able to echo errors and general standard
> output goodness to the screen.
>
> In the FAQ, it points to xchat, but I couldn't find the
> implementation of gray streams there.
Here are parts of my implementation (not fully functional, but you
probably get the idea). lisp.d defines the MEX interface and the
low-level
routines to redirect ECL outputs to MATLAB window. It also defines a
temporary output stream as a string-stream used during the
initialization
process. Finally, it loads minit.lsp (compiled in the MEX file, loaded
through the init_MINIT call), which setup the gray streams.
======
lisp.d
======
static cl_object out_stream = Cnil;
static
@(defun "matlab_invoke_debugger" (condition old_debugger_hook)
@
/* Flush any initialization message */
if ( !Null( out_stream ) )
mexPrintf( "%s", cl_get_output_stream_string( out_stream
)->string.self );
cl_object err_str = cl_format( 4, Cnil, make_constant_string(
"LISP error => ~A~C" ), condition, CODE_CHAR('\0') );
mexErrMsgIdAndTxt( "LISP:error", (char*)err_str->string.self );
@( return Cnil )
@)
static
@(defun "matlab_quit" ()
@
mexWarnMsgIdAndTxt("LISP:quit", "QUIT function is disabled in
LISP, use the 'quit' function from MATLAB instead.");
@(return Cnil)
@)
#define MEX_BUFFER_LEN 128
static char mex_buffer[ MEX_BUFFER_LEN ];
static int mex_buffer_index = 0;
static cl_object matlab_mex_flush()
{
mex_buffer[ mex_buffer_index ] = '\0';
mexPrintf( "%s", mex_buffer );
mex_buffer_index = 0;
@( return Cnil );
}
static cl_object matlab_mex_write_char( cl_object c )
{
assert_type_character( c );
mex_buffer[ mex_buffer_index++ ] = CHAR_CODE( c );
if ( mex_buffer_index == ( MEX_BUFFER_LEN-1 ) || CHAR_CODE(c) ==
'\n')
{
/* time to flush buffer */
matlab_mex_flush();
}
@( return c )
}
void lisp_matlab_init()
{
/* Install temporary I/O streams to catch messages during
initialization */
out_stream = cl_make_string_output_stream( 0 );
ECL_SET( @'*terminal-io*', cl_make_two_way_stream(
cl_make_string_input_stream( 1, make_constant_string( "" ) ),
out_stream ) );
ECL_SET( @'*error-output*', out_stream );
/* Catch errors through invoke-debugger; redefine "quit" */
cl_object mdbg_sym = c_string_to_object("MATLAB-DEBUGGER-HOOK");
cl_def_c_function_va(mdbg_sym, (void*)matlab_invoke_debugger);
ECL_SET( @'*debugger-hook*', mdbg_sym);
cl_def_c_function_va(@'ext::quit', ( void* )matlab_quit);
/* Create "MATLAB" package */
cl_object mpack = make_package( make_constant_string( "MATLAB"
), Cnil, cl_list( 1, make_constant_string( "COMMON-LISP" ) ) );
cl_def_c_function( _intern( "MEX-WRITE-CHAR", mpack ), ( void*
)matlab_mex_write_char, 1 );
cl_def_c_function( _intern( "MEX-FLUSH", mpack ), ( void*
)matlab_mex_flush, 0 );
/* Load initialization file */
cl_object user_pack =
cl_find_package(c_string_to_object("CL-USER"));
read_VV(OBJNULL, init_MINIT);
si_select_package(user_pack);
/* Undefine temporary output stream, as it should have been
redefined in "minit.lsp" */
out_stream = Cnil;
}
=========
minit.lsp
=========
(defclass matlab-stream (ext::fundamental-character-output-stream)
(last-char))
(defun matlab-debug (fmt &rest args)
(with-open-file (f "debug.txt" :direction :output :if-exists :append
:if-does-not-exist :create)
(apply #'format (append (list f fmt) args))))
(defmethod ext::stream-write-char ((stream matlab-stream) c)
;(matlab-debug "Writing char: [~A] ~A~%" (char-code c) c)
(matlab::mex-write-char c))
(defmethod ext::stream-force-output ((stream matlab-stream))
;(matlab-debug "stream-force-output called~%")
(matlab::mex-flush)
t)
(let ((old-io *terminal-io*))
(setq *terminal-io* (make-two-way-stream (make-string-input-stream "")
(make-instance 'matlab-stream)))
(setq *error-output* (two-way-stream-output-stream *terminal-io*))
; Flush any pending message
(and (typep old-io 'two-way-stream) (typep
(two-way-stream-output-stream old-io) 'string-stream)
(format t "~A" (get-output-stream-string
(two-way-stream-output-stream old-io)))))
More information about the ecl-devel
mailing list