funcv_form = """
%s
struct SFunction%sv : IFunction
{
	typedef %s (*FUNC)(%s);

	SFunction%sv(const std::string& name, FUNC func) : IFunction(name), m_func(func) {}

	virtual PyObject*	operator() (PyObject* self, PyObject* args)
	{PYTINKER_CALL(m_func(%s);return PyObject_FromNone())}

	FUNC m_func;
};

%s
IFunction* PyCppFuncv(const std::string& name, %s (*func)(%s))
{return new SFunction%sv%s(name, func);}
"""

funct_form = """
%s
struct SFunction%st : IFunction
{
	typedef %s (*FUNC)(%s);

	SFunction%st(const std::string& name, FUNC func) : IFunction(name), m_func(func) {}

	virtual PyObject*	operator() (PyObject* self, PyObject* args)
	{PYTINKER_CALL(return PyObject_From(m_func(%s)))}

	FUNC m_func;
};

%s
IFunction* PyCppFunct(const std::string& name, %s (*func)(%s))
{return new SFunction%st%s(name, func);}
"""

stdcall_funcv_form = """
%s
struct STDCALL_SFunction%sv : IFunction
{
	typedef %s (__stdcall *FUNC)(%s);

	STDCALL_SFunction%sv(const std::string& name, FUNC func) : IFunction(name), m_func(func) {}

	virtual PyObject*	operator() (PyObject* self, PyObject* args)
	{PYTINKER_CALL(m_func(%s);return PyObject_FromNone())}

	FUNC m_func;
};

%s
IFunction* STDCALL_PyCppFuncv(const std::string& name, %s (__stdcall *func)(%s))
{return new STDCALL_SFunction%sv%s(name, func);}
"""

stdcall_funct_form = """
%s
struct STDCALL_SFunction%st : IFunction
{
	typedef %s (__stdcall *FUNC)(%s);

	STDCALL_SFunction%st(const std::string& name, FUNC func) : IFunction(name), m_func(func) {}

	virtual PyObject*	operator() (PyObject* self, PyObject* args)
	{PYTINKER_CALL(return PyObject_From(m_func(%s)))}

	FUNC m_func;
};

%s
IFunction* STDCALL_PyCppFunct(const std::string& name, %s (__stdcall *func)(%s))
{return new STDCALL_SFunction%st%s(name, func);}
"""

methodv_form = """
%s
struct SMethod%sv : IMethod
{
	typedef %s (%s::*FUNC)(%s);

	SMethod%sv(const std::string& name, FUNC func) : IMethod(name), m_func(func)	{}

	virtual PyObject*	operator() (PyObject* self, PyObject* args)
	{
		%s* cpp_inst = static_cast<%s*>(PyCppInstance_GetCppInstPtr(self));
		assert(NULL != cpp_inst);
		PYTINKER_CALL((cpp_inst->*m_func)(%s);return PyObject_FromNone())
	}

	FUNC m_func;
};

%s
IMethod* PyCppMethodv(const std::string& name, %s (%s::*func)(%s))
{return new SMethod%sv%s(name, func);}
"""


methodt_form = """
%s
struct SMethod%st : IMethod
{
	typedef %s (%s::*FUNC)(%s);

	SMethod%st(const std::string& name, FUNC func) : IMethod(name), m_func(func)	{}

	virtual PyObject*	operator() (PyObject* self, PyObject* args)
	{
		%s* cpp_inst = static_cast<%s*>(PyCppInstance_GetCppInstPtr(self));
		assert(NULL != cpp_inst);
		PYTINKER_CALL(return PyObject_From((cpp_inst->*m_func)(%s)))
	}

	FUNC m_func;
};

%s
IMethod* PyCppMethodt(const std::string& name, %s (%s::*func)(%s))
{return new SMethod%st%s(name, func);}
"""



def BuildHeader(argMaxCount, form, ret="void", cls=""): 
	textList = []
	for argCount in range(argMaxCount+1):
		argNameList = ["ARG%d" % (argIndex+1) for argIndex in range(argCount)]

		typeNameList = argNameList[:]

		if "void" !=  ret:
			typeNameList.insert(0, ret)

		if cls:
			typeNameList.insert(0, cls)

		if typeNameList:
			class_template = "template<%s>" % (", ".join(["typename %s" % typeName for typeName in typeNameList]))
			func_template = class_template

			typesDecl = "<%s>" % ", ".join(typeNameList)
		else:
			class_template = ""
			func_template = "inline"
			typesDecl = ""

		argsDecl = ", ".join(argNameList)
		argsImpl = ", ".join(["arg_<%s>(args, %d)" % (argName, argIndex) for (argIndex, argName) in enumerate(argNameList)])

		postfix = "%d" % (argCount)

		if cls:
			textList.append(form % (class_template, postfix, ret, cls, argsDecl, postfix, cls, cls, argsImpl, func_template, ret, cls, argsDecl, postfix, typesDecl))
		else:
			textList.append(form % (class_template, postfix, ret, argsDecl, postfix, argsImpl, func_template, ret, argsDecl, postfix, typesDecl))
	
	return "\n".join(textList)


if 1:
	file = open("__py_tinker_func_impl.h", "w")
	file.write(BuildHeader(8, funcv_form, "void"))
	file.write(BuildHeader(8, funct_form, "RET"))
	file.write("\n#ifdef _WIN32\n")
	file.write(BuildHeader(8, stdcall_funcv_form, "void"))
	file.write(BuildHeader(8, stdcall_funct_form, "RET"))
	file.write("#endif\n")

	file = open("__py_tinker_method_impl.h", "w")
	file.write(BuildHeader(8, methodv_form, "void", "CLS"))
	file.write(BuildHeader(8, methodt_form, "RET", "CLS"))
else:
	print BuildHeader(3, methodv_form, "void", "CLS")
	#print BuildHeader(3, methodt_form, "RET", "CLS")
	#print BuildHeader(3, funct_form, "", "RET")
