[PD-cvs] externals/clr clr.c, NONE, 1.1 makefile, NONE, 1.1 makefile.darwin, NONE, 1.1 test-clr.pd, NONE, 1.1

dmorelli morellid at users.sourceforge.net
Thu Jan 12 10:22:37 CET 2006


Update of /cvsroot/pure-data/externals/clr
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20032

Added Files:
	clr.c makefile makefile.darwin test-clr.pd 
Log Message:
checking in the external

--- NEW FILE: makefile ---
current: cygwin

clean: ; rm -f *.dll *.o


cygwin: clr.dll	

.SUFFIXES: .dll


# where are the PD header files?
# leave it blank if it is a system directory (like /usr/local/include), 
# 	since gcc 3.2 complains about it
PDPATH=/home/Davide

LINUXCFLAGS = -DPD -O2 -mno-cygwin
#LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \
#    -Wall -W -Wshadow -Wstrict-prototypes -Werror \
#    -Wno-unused -Wno-parentheses -Wno-switch

LINUXINCLUDE =  -I../../src -I$PDPATH

MONOSRC = -ID:/Davide/cygwin/tmp/build_deps/include -ID:/Davide/cygwin/tmp/build_deps/include/glib-2.0 -ID:/Davide/cygwin/tmp/build_deps/lib/glib-2.0/include -ID:/Davide/cygwin/home/Davide/mono/include 
MONOLIB = -LD:/Davide/cygwin/tmp/build_deps/lib -LD:/Davide/cygwin/home/Davide/mono/lib -lmono -lm -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv 

.c.dll:
#	gcc $(LINUXCFLAGS) $(LINUXINCLUDE) `pkg-config --cflags --libs mono` -lm -ID:/Davide/cygwin/home/Davide/mono/include -LD:/Davide/cygwin/home/Davide/mono/lib $*.c
	gcc $(LINUXCFLAGS) $(LINUXINCLUDE) $(MONOSRC) -o $*.o -c $*.c
	gcc -export_dynamic  -shared -mno-cygwin $(MONOLIB) -o $*.dll $*.o -lm pd.dll libmono.dll.a
#	ld -export_dynamic $(MONOLIB) -o $*.dll $*.o -lm pd.dll
#	strip --strip-unneeded $*.pd_linux
#	rm $*.o

--- NEW FILE: test-clr.pd ---
#N canvas 0 0 726 474 12;
#X obj 97 383 clr;
#X obj 105 80 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
-1;
#X msg 239 110 1 2 3;
#X msg 238 136 sel3 a b c;
#X msg 236 176 selFloat 0.5;
#X msg 247 221 selString ciao;
#X msg 247 263 selList 1 2 3;
#X msg 344 161 selFloat \$1;
#X obj 344 121 hsl 128 15 1 2 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 0 1;
#X floatatom 360 142 5 0 0 0 - - -;
#X msg 242 59 sel1;
#X msg 240 87 sel2;
#X obj 428 260 hsl 128 15 1 2 0 0 empty empty empty -2 -6 0 8 -262144
-1 -1 0 1;
#X text 424 239 2nd inlet mapped to selFloat;
#X obj 71 429 print a;
#X msg 239 297 selStringList abba baab caac dede;
#X msg 248 360 selFloatList 1 2 3 4;
#X msg 240 319 selStringList ego filose;
#X connect 0 0 14 0;
#X connect 1 0 0 0;
#X connect 2 0 0 0;
#X connect 3 0 0 0;
#X connect 4 0 0 0;
#X connect 5 0 0 0;
#X connect 6 0 0 0;
#X connect 7 0 0 0;
#X connect 8 0 7 0;
#X connect 8 0 9 0;
#X connect 10 0 0 0;
#X connect 11 0 0 0;
#X connect 12 0 0 1;
#X connect 15 0 0 0;
#X connect 16 0 0 0;
#X connect 17 0 0 0;

--- NEW FILE: makefile.darwin ---
current: pd_darwin

clean: ; rm -f *.pd_linux *.o *.pd_darwin


# ----------------------- Mac OSX -----------------------

pd_darwin: clr.pd_darwin

.SUFFIXES: .pd_darwin


# where are the PD header files?
# leave it blank if it is a system directory (like /usr/local/include), 
# 	since gcc 3.2 complains about it
#PDPATH=/usr/local/src/pd/src
PDPATH=/Users/davide/Desktop/Pd-0.39-0.app/Contents/Resources/src/

# where is the PD executable?
#PD=/usr/local/bin/pd
PD=/Users/davide/Desktop/Pd-0.39-0.app/Contents/Resources/bin/pd
#PD=/Users/davidemorelli/Desktop/robaDavide/Pd-0.38-3.app/Contents/Resources/src/

CFLAGS=`pkg-config --cflags mono`
#LDFLAGS=`pkg-config --libs mono`
LDFLAGS=-L/sw/lib -L/sw/lib/pkgconfig/../../lib -lmono  -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv

DARWININCLUDE =  -I../../src -I$(PDPATH)

#DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \
#   -Wno-unused -Wno-parentheses -Wno-switch

DARWINCFLAGS = -DPD -O2 

.c.pd_darwin:
	cc $(DARWINCFLAGS) $(DARWININCLUDE) $(CFLAGS) -o $*.o -c $*.c
#	cc -bundle  -bundle_loader $(PD) -multiply_defined supress $(LDFLAGS) -o $*.pd_darwin  *.o
	cc -bundle  -bundle_loader $(PD) -flat_namespace $(LDFLAGS) -o $*.pd_darwin  *.o
#	cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $(FANNLIB) *.o
#	rm -f $*.o

--- NEW FILE: clr.c ---
/* 
just a dummy clr patch 

*/

#include "m_pd.h"

#include <time.h>
#include <math.h>
#include <stdlib.h>

// mono
#include <mono/jit/jit.h>
#include <mono/metadata/object.h>
#include <mono/metadata/environment.h>
#include <mono/metadata/assembly.h>
#include <mono/metadata/debug-helpers.h>
#include <string.h>
#include <stdlib.h>

#define MAX_SELECTORS 256
#define MAX_OUTLETS 32

void *clr_new(t_symbol *s, int argc, t_atom *argv);

// list of mono methods
typedef struct selectorList selectorList;
typedef struct selectorList
{
	char *sel; // the selector
	MonoMethod *func; // the function
	int type;
//	selectorList *next; // next element of the list
};

// list of outlets
typedef struct outletList outletList;
typedef struct outletList
{
	t_outlet *outlet_pointer;
//	selectorList *next; // next element of the list
};

static t_class *clr_class;

typedef struct _clr
{
    t_object x_obj; // myself
	t_outlet *l_out;
	// mono stuff
	MonoDomain *domain;
	MonoAssembly *assembly;
	MonoObject *obj;
	MonoMethod *method, *setUp;
	MonoClass *klass;
	int n;

	selectorList selectors[MAX_SELECTORS];
	outletList outlets[MAX_OUTLETS];

} t_clr;


// mono functions

static void mono_clean(t_clr *x)
{
	// clean up stuff
	mono_jit_cleanup (x->domain);

}

void registerMonoMethod(void *x, MonoString *selectorString, MonoString *methodString, int type);
void createInlet(void *x1, MonoString *selectorString, int type);
void createOutlet(void *x1, int type);
void out2outlet(void *x, int outlet, int type, unsigned char  *val  /* TODO */);
void post2pd(MonoString *mesString);
void error2pd(MonoString *mesString);

// load the variables and init mono
static void mono_load(t_clr *x)
{
//	const char *file="D:\\Davide\\cygwin\\home\\Davide\\externalTest1.dll";
	const char *file="PureData.dll";
	MonoImage *image;
	MonoMethod *m = NULL, *ctor = NULL, *fail = NULL, *mvalues;
	gpointer iter;
	gpointer args [1];
	int val;
	int i;
	double rnd;
	int random_name_int;
	char random_name_str[256];
	srand( (unsigned)time( NULL ) );
	rnd = rand()/((double)RAND_MAX + 1);
	random_name_int =(int) (rnd * RAND_MAX);
	sprintf(random_name_str, "%s-%i",file, random_name_int);

	// prepare the selectors list
	for (i=0; i<MAX_SELECTORS; i++)
	{
		x->selectors[i].sel = 0;
		x->selectors[i].func = 0;
	}
	// and the outlets list
	for (i=0; i<MAX_OUTLETS; i++)
	{
		x->outlets[i].outlet_pointer = 0;
	}

printf("will load %s, random_name %s\n", file, random_name_str);

	x->domain = mono_jit_init (random_name_str);

		// add mono to C hooks
	mono_add_internal_call ("PureData.pd::RegisterSelector", registerMonoMethod);
	mono_add_internal_call ("PureData.pd::ToOutlet", out2outlet);
	mono_add_internal_call ("PureData.pd::PostMessage", post2pd);
	mono_add_internal_call ("PureData.pd::ErrorMessage", error2pd);
	mono_add_internal_call ("PureData.pd::CreateOutlet", createOutlet);
	mono_add_internal_call ("PureData.pd::CreateInlet", createInlet);

	x->assembly = mono_domain_assembly_open (x->domain, file);
	if (!x->assembly)
	{
		error("clr: assembly not found!");
	}

	image = mono_assembly_get_image (x->assembly);

	
	x->klass = mono_class_from_name (image, "PureData", "External");
	if (!x->klass) {
		error("Can't find MyType in assembly %s\n", mono_image_get_filename (image));
		//exit (1);
	}
	x->obj = mono_object_new (x->domain, x->klass);
	mono_runtime_object_init (x->obj);

	/* retrieve all the methods we need */
	iter = NULL;
	while ((m = mono_class_get_methods (x->klass, &iter))) {
		if (strcmp (mono_method_get_name (m), "test") == 0) {
			x->method = m;
		} else if (strcmp (mono_method_get_name (m), "SetUp") == 0) {
			x->setUp = m;
		} else if (strcmp (mono_method_get_name (m), "Fail") == 0) {
			fail = m;
		} else if (strcmp (mono_method_get_name (m), "Values") == 0) {
			mvalues = m;
		} else if (strcmp (mono_method_get_name (m), ".ctor") == 0) {
			/* Check it's the ctor that takes two args:
			 * as you see a contrsuctor is a method like any other.
			 */
			MonoMethodSignature * sig = mono_method_signature (m);
			if (mono_signature_get_param_count (sig) == 2) {
				ctor = m;
			}
		}
	}

	// call the base functions
	if (x->setUp)
	{
		val = x;
		args [0] = &val;
		mono_runtime_invoke (x->setUp, x->obj, args, NULL);
		post("SetUp() invoked");

	} else
	{
		error("clr: the provided assembly is not valid! the SetUp function is missing");
	}


}

/*
// call the method
static void clr_bang(t_clr *x) {

	gpointer args [2];
	int val;
	MonoObject *result;

	val = x->n;
	args [0] = &val;

	if (x->method)
	{
		result = mono_runtime_invoke (x->method, x->obj, args, NULL);
		val = *(int*)mono_object_unbox (result);
		x->n = val;
	//	outlet_float(x->l_out, (float) x->n);
	}


}
*/

// finds a method from its name
void findMonoMethod( MonoClass *klass, char *function_name, MonoMethod **met)
{
	int trovato;
	MonoMethod *m = NULL;
	gpointer iter;
	iter = NULL;
	while (m = mono_class_get_methods (klass, &iter)) 
	{
		if (strcmp (mono_method_get_name (m), function_name) == 0) 
		{
			*met = m;
//printf("%s trovata\n", function_name);
			return;
		} 	
	}
}

void clr_free(t_clr *x)
{
	mono_clean(x);
}

// here i look for the selector and call the right mono method
void clr_manage_list(t_clr *x, t_symbol *sl, int argc, t_atom *argv)
{
	gpointer args [2];
	int valInt;
	float valFloat;

	int i;
	// first i extract the first atom which should be a symbol
	//post("clr_manage_list, got symbol = %s", sl->s_name);

	for (i=0; i<MAX_SELECTORS; i++)
	{
		if (strcmp(x->selectors[i].sel, sl->s_name) == 0)
		{
			// I've found the selector!
printf("selector %s, func %s\n", sl->s_name, x->selectors[i].sel);
			if (x->selectors[i].func)
			{
				// ParametersType {None = 0, Float=1, Symbol=2, List=3};
				switch (x->selectors[i].type)
				{
				case 0:
					mono_runtime_invoke (x->selectors[i].func, x->obj, NULL, NULL);
					break;
				case 1:
					{
						gpointer args [1];
						float val = atom_getfloat(argv);
						args[0] = &val;
						mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
						break;
					}
				case 2:
					{
						gpointer args [1];
						t_symbol *strsymbol;
						MonoString *strmono;
						strsymbol = atom_getsymbol(argv);
						strmono = mono_string_new (x->domain, strsymbol->s_name);
						args[0] = &strmono;
						mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
						// memory leak ?
						break;
					}
				case 3:
					{
						gpointer args [1];
						MonoString *strmono;
						t_symbol *strsymbol;
						char *str;
						MonoArray * arystr;
						int j;
printf("preparo l'array\n");
						
						arystr = mono_array_new (x->domain, mono_get_string_class (), argc);
						for (j=0; j<argc; j++)
						{
							int * ftmp = malloc(sizeof(int));
								*ftmp =  j;
							strsymbol = atom_getsymbol(argv+j);
							MonoString *arg = mono_string_new (x->domain, strsymbol->s_name);
							mono_array_set (arystr, MonoString *, j, arg);
							// gpointer
							//mono_array_set (arystr, gint32 , j, ftmp);


						}
						args[0] = arystr;
						
						//args[0] = strings;
printf("mando a mono\n");
						mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
printf("ho mandatao a mono\n");
						break;
					}
				}
				
				//result = mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL);
				//val = *(int*)mono_object_unbox (result);
				//x->n = val;
				return;
			}
		}
		if (x->selectors[i].func == 0)
			i = MAX_SELECTORS;
	}

	error("clr: selector not recognized");

}

// this function is called by mono when it wants to register a selector callback
void registerMonoMethod(void *x1, MonoString *selectorString, MonoString *methodString, int type)
{
	
	char *selCstring, *metCstring;
	MonoMethod *met;
	t_clr *x;
	int this_selector, i;
	//int ret;

	
    selCstring = mono_string_to_utf8 (selectorString);
	metCstring = mono_string_to_utf8 (methodString);
	
	x = (t_clr *)x1;

	//ret = 0;
	met = 0;
	findMonoMethod( x->klass, metCstring, &met);

	if (!met)
	{
		error("method not found!");
		return;
	}

	post("registerMonoMethod: associating %s to %s", selCstring, metCstring);

	this_selector = MAX_SELECTORS;
	for (i = 0; i < MAX_SELECTORS; i++)
	{
		if (x->selectors[i].func == 0)
		{
			// i found the first empty space
			this_selector = i;
			i = MAX_SELECTORS;
		}
		
	}
	if (this_selector == MAX_SELECTORS)
	{
		error("not enough space for selectors! MAX_SELECTORS = %i", MAX_SELECTORS);
		return;
	}

	x->selectors[this_selector].sel = selCstring;
	x->selectors[this_selector].func = met;
	x->selectors[this_selector].type = type;

	class_addmethod(clr_class, (t_method)clr_manage_list, gensym(selCstring), A_GIMME, 0);


}

// this function is called by mono when it wants to create a new inlet
void createInlet(void *x1, MonoString *selectorString, int type)
{
	// public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5};
	char *selCstring;
	char typeString[256];
	t_clr *x;

    selCstring = mono_string_to_utf8 (selectorString);	
	x = (t_clr *)x1;

	switch (type)
	{
	case 1:
		sprintf(typeString, "float");
		break;
	case 2:
		sprintf(typeString, "symbol");
		break;
	case 3:
		sprintf(typeString, "list");
		break;
	case 4:
		sprintf(typeString, "bang");
		break;
	default:
		sprintf(typeString, "");
		break;
	}
	// create the inlet
	inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym(typeString), gensym(selCstring));
}

// this function is called by mono when it wants to create a new outlet
void createOutlet(void *x1, int type)
{
	t_clr *x;
	int i = 0;
	char typeString[256];
	x = (t_clr *)x1;

	// public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5};
	switch (type)
	{
	case 1:
		sprintf(typeString, "float");
		break;
	case 2:
		sprintf(typeString, "symbol");
		break;
	case 3:
		sprintf(typeString, "list");
		break;
	case 4:
		sprintf(typeString, "bang");
		break;
	default:
		sprintf(typeString, "");
		break;
	}

	while (i < MAX_OUTLETS)
	{
		if (x->outlets[i].outlet_pointer == 0)
		{
			// empty space found!
			x->outlets[i].outlet_pointer = outlet_new(&x->x_obj, gensym(typeString));
			return;
		}
		i++;
	}
	error("the maximum number of outlets has been reached (%i)", MAX_OUTLETS);
	
}

// out to outlet
void out2outlet(void *x1, int outlet, int type, unsigned char *val /* TODO */)
{
	t_clr *x;
	x = (t_clr *)x1;
	t_atom *lista;

	if ((outlet>MAX_OUTLETS) || (outlet<0))
	{
		error("outlet number out of range, max is %i", MAX_OUTLETS);
		return;
	}
	if (x->outlets[outlet].outlet_pointer == 0)
	{
		error("outlet %i not registered", outlet);
		return;
	}
printf("ricevuto %i %i\n", val[0], val[1]);
if (val[0]==0x01)
	printf("val[0]==0x00");

	lista = (t_atom *) malloc(sizeof(t_atom) * 2);
	SETFLOAT(lista, (float) val[0]);
	SETFLOAT(lista+1, (float) val[1]);
	outlet_anything(x->outlets[outlet].outlet_pointer,
					gensym("list") ,
					2, 
					lista);
	free(lista);
}

// this function is called by mono when it wants post messages to pd
void post2pd(MonoString *mesString)
{
	
	char *mesCstring;
    mesCstring = mono_string_to_utf8 (mesString);
	post(mesCstring);
	
}

// this function is called by mono when it wants to post errors to pd
void error2pd(MonoString *mesString)
{
	
	char *mesCstring;
    mesCstring = mono_string_to_utf8 (mesString);
	error(mesCstring);
}
/*
//void ext_class_addbang(const char *funcName)
void ext_class_addbang(t_method funcName)
{
//	class_addbang(clr_class, (t_method)clr_bang);
	class_addbang(clr_class, funcName);
}*/

void *clr_new(t_symbol *s, int argc, t_atom *argv)
{

	int i;
	time_t a;
    t_clr *x = (t_clr *)pd_new(clr_class);
//	x->l_out = outlet_new(&x->x_obj, &s_list);
//	x->l_out = outlet_new(&x->x_obj, gensym("float"));
	


	x->n = 0;
	// load mono, init the needed vars
	mono_load(x);

    return (x);
}

void clr_setup(void)
{
    clr_class = class_new(gensym("clr"), (t_newmethod)clr_new,
        (t_method)clr_free, sizeof(t_clr), CLASS_DEFAULT, A_GIMME, 0);
    //class_addbang(clr_class, (t_method)clr_bang);
//	ext_class_addbang((t_method) clr_bang);

	class_addlist(clr_class, (t_method)clr_manage_list);

}





More information about the Pd-cvs mailing list