diff --git a/src/vasingletonmethods.hpp b/src/vasingletonmethods.hpp
index 67506bc8f9c7ddbc48a168956d2082ed35668fa3..b10c9f3d91aaa9d638495864d1170a8fd20a1e97 100644
--- a/src/vasingletonmethods.hpp
+++ b/src/vasingletonmethods.hpp
@@ -42,7 +42,63 @@ PyObject* ConvertVAStructToPythonDict( const CVAStruct& oInStruct )
 //! Helper to convert recursively from Python dict to VAStruct
 CVAStruct ConvertPythonDictToVAStruct( PyObject* pInDict )
 {
-	return CVAStruct();
+	CVAStruct oReturn;
+
+	PyObject* pKeyList = PyDict_Keys(pInDict);
+	PyObject* pValueList = PyDict_Values(pInDict);
+
+	for (Py_ssize_t i = 0; i < PyList_Size(pKeyList); i++)
+	{
+		PyObject* pKey = PyList_GetItem(pKeyList, i);
+		PyObject* pValue = PyList_GetItem(pValueList, i);
+		char* pcKeyName = nullptr;
+		if (!PyArg_Parse(pKey, "s", &pcKeyName))
+			VA_EXCEPT2(CVAException::INVALID_PARAMETER, "Invalid key '" + std::string( pcKeyName ) + "'");
+
+		if (Py_None == pValue)
+		{
+			oReturn[pcKeyName] = false;
+		}
+		else if (PyBool_Check(pValue))
+		{
+			oReturn[pcKeyName] = bool(PyLong_AsLong(pValue));
+		}
+		else if (PyLong_Check(pValue))
+		{
+			oReturn[pcKeyName] = PyLong_AsLong(pValue);
+		}
+		else if (PyFloat_Check(pValue))
+		{
+			oReturn[pcKeyName] = PyFloat_AsDouble(pValue);
+		}
+		else if (PyUnicode_Check(pValue))
+		{
+			char* pcStringValue = nullptr;
+			if (!PyArg_Parse(pValue, "s", &pcStringValue))
+				VA_EXCEPT2(CVAException::INVALID_PARAMETER, "Invalid string value at key '" + std::string(pcKeyName) + "': " + std::string(pcStringValue));
+			oReturn[pcKeyName] = std::string(pcStringValue);
+		}
+		else if (PyDict_Check(pValue))
+		{
+			oReturn[pcKeyName] = ConvertPythonDictToVAStruct( pValue);
+		}
+		else if (PyList_Check(pValue))
+		{
+			// Sample buffer
+			VA_EXCEPT_NOT_IMPLEMENTED;
+		}
+		else if (PyByteArray_Check(pValue))
+		{
+			// Data blob
+			VA_EXCEPT_NOT_IMPLEMENTED;
+		}
+		else
+		{
+			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret value of key '" + std::string(pcKeyName) + "' as a supported VAStruct type.")
+		}
+	}
+
+	return oReturn;
 };
 
 
@@ -126,21 +182,21 @@ static PyObject* va_call_module(PyObject* pSelf, PyObject** ppArgs, Py_ssize_t n
 {
 	VAPY_REQUIRE_CONN_TRY;
 	
-	static const char * const _keywords[] = { "module_name", "arguments", NULL };
-	static _PyArg_Parser _parser = { "so:call_module", _keywords, 0 };
+	static const char * const _keywords[] = { "module_name", "arguments_dict", NULL };
+	static _PyArg_Parser _parser = { "sO!:call_module", _keywords, 0 };
 	char* pcModuleName = nullptr;
-	PyObject* pArguments = nullptr;
+	PyObject* pArgumentsDict = nullptr;
 
-	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcModuleName, &pArguments ) )
+	if( !_PyArg_ParseStack( ppArgs, nArgs, pKeywordNames, &_parser, &pcModuleName, &PyDict_Type, &pArgumentsDict ) )
 		return NULL;
 	
 	std::string sModuleName = std::string( pcModuleName );
-	CVAStruct oArgs = ConvertPythonDictToVAStruct( pArguments );
-	CVAStruct oReturn;
+	CVAStruct oInArgs = ConvertPythonDictToVAStruct( pArgumentsDict );
+	CVAStruct oOutArgs;
 
-	g_pVANetClient->GetCoreInstance()->CallModule( sModuleName, oArgs, oReturn );
+	g_pVANetClient->GetCoreInstance()->CallModule( sModuleName, oInArgs, oOutArgs );
 
-	return ConvertVAStructToPythonDict( oReturn );
+	return ConvertVAStructToPythonDict( oOutArgs );
 	
 	VAPY_CATCH_RETURN;
 };