-
Notifications
You must be signed in to change notification settings - Fork 747
Improve method binding #974
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 1 commit
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
21528ee
Add test for ienumerable method
koubaa b4d60c6
Add tests for collection & task/action from function
koubaa 3f02abf
Add more tests
koubaa 9c3e1c5
Implement list converter
koubaa b9db0f6
Implement action converter
koubaa 4b0a1ad
add TODO
koubaa 8bed1bb
Update changelog
koubaa a4599d9
share common code between ToArray and ToList
koubaa 96fd896
improve ref counting
koubaa c6fd768
revert whitespace
koubaa e63d11e
list wrapper
koubaa File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev
Previous commit
list wrapper
- Loading branch information
commit e63d11edc73f7fa197e76681e0316124d53b77c2
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace Python.Runtime { | ||
/// <summary> | ||
/// Implements IEnumerable<typeparamref name="T"/> for any python iterable. | ||
/// </summary> | ||
internal class IterableWrapper<T> : IEnumerable<T> { | ||
private IntPtr iterObject; | ||
|
||
public IterableWrapper(IntPtr value) { | ||
iterObject = Runtime.PyObject_GetIter(value); | ||
if (iterObject == IntPtr.Zero) | ||
Exceptions.RaiseTypeError("not an iterator"); | ||
Runtime.XIncref(iterObject); | ||
} | ||
~IterableWrapper() { | ||
Runtime.XDecref(iterObject); | ||
} | ||
|
||
public IEnumerator<T> GetEnumerator() { | ||
return GetEnumerator(); | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() { | ||
IntPtr item; | ||
while ((item = Runtime.PyIter_Next(iterObject)) != IntPtr.Zero) { | ||
object obj = null; | ||
if (!Converter.ToManaged(item, typeof(T), out obj, true)) { | ||
Runtime.XDecref(item); | ||
Runtime.XDecref(iterObject); | ||
Exceptions.RaiseTypeError("wrong type in sequence"); | ||
} | ||
|
||
Runtime.XDecref(item); | ||
yield return obj; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Implements IList<typeparamref name="T"/> for any python sequence. | ||
/// Some methods/properties are only available on certaintypes of sequences, like list | ||
/// </summary> | ||
internal class ListWrapper<T> : IterableWrapper<T>, IList<T> | ||
{ | ||
private IntPtr seq; | ||
public ListWrapper(IntPtr value) : base(value) | ||
{ | ||
this.seq = value; | ||
Runtime.XIncref(value); | ||
bool IsSeqObj = Runtime.PySequence_Check(value); | ||
if (!IsSeqObj) | ||
Exceptions.RaiseTypeError("not a sequence"); | ||
|
||
} | ||
~ListWrapper() | ||
{ | ||
Runtime.XDecref(seq); | ||
} | ||
public T this[int index] | ||
{ | ||
get | ||
{ | ||
IntPtr item = Runtime.PySequence_GetItem(seq, index); | ||
object obj; | ||
|
||
if (!Converter.ToManaged(item, typeof(T), out obj, true)) { | ||
Runtime.XDecref(item); | ||
Exceptions.RaiseTypeError("wrong type in sequence"); | ||
} | ||
|
||
return (T)obj; | ||
} | ||
set | ||
{ | ||
IntPtr pyItem = Converter.ToPython(value, typeof(T)); | ||
if (pyItem == IntPtr.Zero) | ||
throw new Exception("failed to set item"); | ||
|
||
var result = Runtime.PySequence_SetItem(seq, index, pyItem); | ||
Runtime.XDecref(pyItem); | ||
if (result == -1) | ||
throw new Exception("failed to set item"); | ||
} | ||
} | ||
|
||
public int Count | ||
{ | ||
get | ||
{ | ||
var len = Runtime.PySequence_Size(seq); | ||
return (int)len; | ||
} | ||
} | ||
|
||
public bool IsReadOnly | ||
{ | ||
get | ||
{ | ||
return Runtime.PyTuple_Check(seq); //python tuples are immutable | ||
} | ||
|
||
} | ||
|
||
public void Add(T item) { | ||
if (IsReadOnly) | ||
throw new NotImplementedException(); | ||
|
||
//only implemented if this is a list! | ||
if (!Runtime.PyList_Check(seq)) | ||
throw new NotImplementedException(); | ||
|
||
IntPtr pyItem = Converter.ToPython(item, typeof(T)); | ||
if (pyItem == IntPtr.Zero) | ||
throw new Exception("failed to add item"); | ||
|
||
var result = Runtime.PyList_Append(seq, pyItem); | ||
Runtime.XDecref(pyItem); | ||
if (result == -1) | ||
throw new Exception("failed to add item"); | ||
} | ||
|
||
public void Clear() { | ||
if (IsReadOnly) | ||
throw new NotImplementedException(); | ||
var result = Runtime.PySequence_DelSlice(seq, 0, Count); | ||
if (result == -1) | ||
throw new Exception("failed to clear sequence"); | ||
} | ||
|
||
public bool Contains(T item) | ||
{ | ||
//not sure if IEquatable is implemented and this will work! | ||
foreach (var element in this) | ||
if (element.Equals(item)) return true; | ||
|
||
return false; | ||
} | ||
|
||
public void CopyTo(T[] array, int arrayIndex) | ||
{ | ||
for (int index = 0; index < Count; index++) | ||
{ | ||
array[index + arrayIndex] = this[index]; | ||
} | ||
} | ||
|
||
public int IndexOf(T item) { | ||
var index = 0; | ||
foreach (var element in this) { | ||
if (element.Equals(item)) return index; | ||
index++; | ||
} | ||
|
||
return -1; | ||
} | ||
|
||
public void Insert(int index, T item) | ||
{ | ||
if (IsReadOnly) | ||
throw new NotImplementedException(); | ||
|
||
//only implemented if this is a list! | ||
if (!Runtime.PyList_Check(seq)) | ||
throw new NotImplementedException(); | ||
|
||
IntPtr pyItem = Converter.ToPython(item, typeof(T)); | ||
if (pyItem == IntPtr.Zero) | ||
throw new Exception("failed to insert item"); | ||
|
||
var result = Runtime.PyList_Insert(seq, index, pyItem); | ||
Runtime.XDecref(pyItem); | ||
if (result == -1) | ||
throw new Exception("failed to insert item"); | ||
} | ||
|
||
public bool InternalRemoveAt(int index) | ||
{ | ||
if (IsReadOnly) | ||
throw new NotImplementedException(); | ||
if (index >= Count || index < 0) | ||
throw new IndexOutOfRangeException(); | ||
|
||
return Runtime.PySequence_DelItem(seq, index) != 0; | ||
} | ||
|
||
public bool Remove(T item) | ||
{ | ||
return InternalRemoveAt(IndexOf(item)); | ||
} | ||
|
||
public void RemoveAt(int index) | ||
{ | ||
InternalRemoveAt(index); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can't use
XDecref
directly in destructor, seeRuntime.PyObject
's destructor, you can just refer aPyObject
, it can let you have no need concern about about the release.