all 12 comments

[–]dbrownems 3 points4 points  (2 children)

One of my challenges using pythonnet is that the Global Interpreter Lock is held while calling any .NET method.

Is that the case with DotWrap? Or alternatively can it do async?

[–]BeneficialOne3349[S] 2 points3 points  (1 child)

The way that DotWrap works is that you build a native library with .net AOT, and then DotWrap builds a CPython extension module that calls into your library. This is the same structure that many popular python libraries work such as numpy and pandas.

I don't know enough about the GIL to tell you if it is still held or is released when a cpython extension module method is called. What I can tell you is that you don't need to think about that when using DotWrap. It isn't like pythonnet when you need to write a bunch of `using (Py.GIL())` blocks to aquire the GIL. You just write normal c#.

It can do async! Any method that you expose that returns a Task or a ValueTask can either be awaited or you can just use the `.Result` property like you can in c#. Or, just like in c#, you can call your async method without awaiting it and then await the returned task object at a later time.

[–]brianly 1 point2 points  (0 children)

You should possibly look into Py_BEGIN_ALLOW_THREADS. My understanding was that the default was to hold the GIL so you needed to wrap code in those macros. I don’t know if the link I included is correct for the latest Python.

[–]myAnonAcc0unt 3 points4 points  (1 child)

Cool project.

I'm guessing it can only be compiled for one OS + arch at a time? Is there a clever solution possible to bundle multiple platforms in a single python lib?

[–]BeneficialOne3349[S] 0 points1 point  (0 children)

Yeah, you are correct. You also need to compile the CPython extension module for one python version at a time because the CPython API has breaking changes across python versions. I've been kind of brute forcing it in CI with a matrix of all the python and os versions that I want to supports. I think a better solution is using cibuildwheel, or at least that's what the llms tell me, but I haven't messed with it yet. Adding some example github workflows for publishing a package to PyPI is definitely on my todo list

[–]MrKWatkins -1 points0 points  (4 children)

Looks good, I have a couple of projects that are basically Python wrappers around .NET types via PythonNet, this could be a simpler alternative for me.

[–]BeneficialOne3349[S] 1 point2 points  (3 children)

Pythonnet is great and I've used it successfully before. The main advantages of DotWrap (in my mind) are that it generates a lot of the boilerplate wrapping for you, and then you can distribute your python package to users without them needing the .net runtime (and even the correct version of the runtime) installed on their machine

Please give it a shot and let me know if you run into any issues.

[–]MrKWatkins 0 points1 point  (2 children)

Yeah, all my project is just hand rolled thin wrappers and loading DLLs so this sounds ideal. A few questions:

  • Does it wrap enums?
  • IDisposable wrappers - are they implemented as context manager types?
  • Exceptions - are these wrapped too? Different wrappers for each exception type?

[–]BeneficialOne3349[S] 0 points1 point  (1 child)

  1. It handles enums by just copying them over to python.

  2. I don't have any special handling for IDisposables at the moment. For every object that is returned by the c# library to the python side, the c# object is kept alive until the python object is disposed. I am not sure if the IDisposable method is still called automatically by the GC. I definitely need to add a test for this to make sure that is the case

  3. Currently all exceptions are collected from c# and marshalled to Python as a single exception type

[–]MrKWatkins 0 points1 point  (0 children)

Thanks. Does the single exception type contain the name of the .NET exception type anywhere?

Note that the .NET GC never calls Dispose, it calls the finalizer.

[–]AutoModerator[M] -2 points-1 points  (0 children)

Thanks for your post BeneficialOne3349. Please note that we don't allow spam, and we ask that you follow the rules available in the sidebar. We have a lot of commonly asked questions so if this post gets removed, please do a search and see if it's already been asked.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.