Skip to content

Commit

Permalink
improved marshaller to be accessed from cpython language impl
Browse files Browse the repository at this point in the history
  • Loading branch information
eirannejad committed May 16, 2024
1 parent 7d015f8 commit ec836ad
Showing 1 changed file with 76 additions and 51 deletions.
127 changes: 76 additions & 51 deletions src/runtime/McNeel.PythonEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -743,10 +743,16 @@ class MarshContext
public void Pop() => _parents.Pop();
}

public object CreateMarshContext() => new MarshContext();

public object CreatePyList() => new PyList();

// NOTE:
// ensures incoming data is marshalled into
// closest-matching Python objects
public PyObject MarshInput(object value) => MarshInput(value, new MarshContext());
public object MarshInput(object value) => MarshInput(value, new MarshContext());

public object MarshInput(object value, object context) => MarshInput(value, (MarshContext)context);

PyObject MarshInput(object value, MarshContext context)
{
Expand All @@ -770,47 +776,54 @@ PyObject MarshInput(object value, MarshContext context)
// marshall dotnet lists and dictionaries into python list and dict
if (IsGenericType(valueType, typeof(List<>)))
{
IList list = (IList)value;
return MarshInputList((IList)value, context);
}

context.Push(list);
if (IsGenericType(valueType, typeof(Dictionary<,>)))
{
return MarshInputDict((IDictionary)value, context);
}

PyList pyList = new PyList();
foreach (object obj in list)
{
pyList.Append(MarshInput(obj, context));
}
return MarshToPyObject(value);
}

context.Pop();
PyObject MarshInputList(IList value, MarshContext context)
{
context.Push(value);

return pyList;
PyList pyList = new PyList();
foreach (object obj in value)
{
pyList.Append(MarshInput(obj, context));
}

if (IsGenericType(valueType, typeof(Dictionary<,>)))
{
IDictionary dict = (IDictionary)value;
context.Push(dict);
context.Pop();

PyDict pyDict = new PyDict();
foreach (object item in dict)
{
switch (item)
{
case KeyValuePair<object, object> pair:
pyDict[MarshInput(pair.Key, context)] = MarshInput(pair.Value, context);
break;
return pyList;
}

case DictionaryEntry entry:
pyDict[MarshInput(entry.Key, context)] = MarshInput(entry.Value, context);
break;
}
}
PyObject MarshInputDict(IDictionary value, MarshContext context)
{
context.Push(value);

context.Pop();
PyDict pyDict = new PyDict();
foreach (object item in value)
{
switch (item)
{
case KeyValuePair<object, object> pair:
pyDict[MarshInput(pair.Key, context)] = MarshInput(pair.Value, context);
break;

return pyDict;
case DictionaryEntry entry:
pyDict[MarshInput(entry.Key, context)] = MarshInput(entry.Value, context);
break;
}
}

return MarshToPyObject(value);
context.Pop();

return pyDict;
}

PyObject MarshToPyObject(object value)
Expand All @@ -824,6 +837,8 @@ PyObject MarshToPyObject(object value)
// closest-matching dotnet objects
public object MarshOutput(object value) => MarshOutput(value, new MarshContext());

public object MarshOutput(object value, object context) => MarshOutput(value, (MarshContext)context);

object MarshOutput(object value, MarshContext context)
{
if (context.IsSeen(value))
Expand All @@ -850,29 +865,10 @@ object MarshOutput(object value, MarshContext context)
return fromPylist;

case List<object> list:
context.Push(list);

var fromClrList = new List<object>();
foreach (object obj in list)
{
fromClrList.Add(MarshOutput(obj, context));
}

context.Pop();

return fromClrList;
return MarshOutputList(list, context);

case Dictionary<object, object> dict:
context.Push(dict);

var fromClrDict = dict.Select(p =>
{
return new KeyValuePair<object, object>(MarshOutput(p.Key, context), MarshOutput(p.Value, context));
}).ToDictionary(p => p.Key, p => p.Value);

context.Pop();

return fromClrDict;
return MarshOutputDict(dict, context);

case PyObject pyObj:
return MarshFromPyObject(pyObj, context);
Expand Down Expand Up @@ -981,6 +977,35 @@ object MarshFromPyObject(PyObject pyObj, MarshContext context)
return pyObj;
}

object MarshOutputList(List<object> value, MarshContext context)
{
context.Push(value);

var fromClrList = new List<object>();
foreach (object obj in value)
{
fromClrList.Add(MarshOutput(obj, context));
}

context.Pop();

return fromClrList;
}

object MarshOutputDict(Dictionary<object, object> value, MarshContext context)
{
context.Push(value);

var fromClrDict = value.Select(p =>
{
return new KeyValuePair<object, object>(MarshOutput(p.Key, context), MarshOutput(p.Value, context));
}).ToDictionary(p => p.Key, p => p.Value);

context.Pop();

return fromClrDict;
}

static bool IsGenericType(Type type, Type genericType)
{
while (type != null && type != typeof(object))
Expand Down

0 comments on commit ec836ad

Please sign in to comment.