Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Dotnetcore System.UInt32 conversion issues #950

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
jmlidbetter opened this issue Aug 30, 2019 · 10 comments
Closed

Dotnetcore System.UInt32 conversion issues #950

jmlidbetter opened this issue Aug 30, 2019 · 10 comments

Comments

@jmlidbetter
Copy link
Contributor

Environment

  • Pythonnet version: 2.4.0
  • Python version: 3.6.5
  • Operating System: Centos 7 64bit

Details

  • Creating UInt32 in python with a value greater than 0x7FFFFFFF in dotnetcore will cause an overflow error. This is due (seemingly) to the fact that .NET core clr will cast the uint to a signed long (64 bits in size on my system) before calling the PyLong_FromUsignedLong function. Using GDB and breaking before the errornous overflow we can examine the created PyLongObject:

The PyLongObject given to C# by the python interpretter that can be converted to a uint using PyLong_AsUnsignedLong

image

Using PyLong_FromUnsignedLong on the resulting uint gives this:

image

I have raised an issue on the coreclr project: Issue 26444

FYI changing the function definition from

internal static extern IntPtr PyLong_FromUnsignedLong(uint value);

to

internal static extern IntPtr PyLong_FromUnsignedLong(ulong value);

fixes the issue.

@filmor
Copy link
Member

filmor commented Sep 11, 2019

Well, this is problematic. We want to be platform-independent, but C's unsigned long that is used in Python is 64bit on most 64bit Unices and 32bit on Windows, so the uint parameter is indeed wrong.

@Cronan
Copy link
Contributor

Cronan commented Sep 11, 2019 via email

@filmor
Copy link
Member

filmor commented Sep 18, 2019

As far as I can tell, Python is completely oblivious to this difference as it "lives" on the C platform, so all compiled modules will have the same idea of what long means. We can pretty reliably decide this by looking at the platform we are running on in .NET, though. We are already providing internally booleans for IsWindows and Is32Bit here https://github.com/pythonnet/pythonnet/blob/master/src/runtime/runtime.cs#L106-L109.

@jmlidbetter
Copy link
Contributor Author

As far as I can tell, Python is completely oblivious to this difference as it "lives" on the C platform, so all compiled modules will have the same idea of what long means. We can pretty reliably decide this by looking at the platform we are running on in .NET, though. We are already providing internally booleans for IsWindows and Is32Bit here https://github.com/pythonnet/pythonnet/blob/master/src/runtime/runtime.cs#L106-L109.

Would this method get caught out if, for whatever reason, someone is using CPython compiled with 64bit longs on Win64 or CPython compiled with 32bit longs on 64bit Linux?

@jmlidbetter
Copy link
Contributor Author

What we really need is some hook or proxy into sizeof(long).

@Cronan
Copy link
Contributor

Cronan commented Sep 24, 2019

As per a discussion with Joe, It seems the correct way to do this would be with a call to struct.calcsize('P') which can be done in runtime.cs, in InitializePlatformData(). This gives us the bitness of the interpreter architecture, rather than the platform architecture.

@jmlidbetter jmlidbetter mentioned this issue Sep 25, 2019
4 tasks
@filmor
Copy link
Member

filmor commented Sep 26, 2019

As far as I can tell, Python is completely oblivious to this difference as it "lives" on the C platform, so all compiled modules will have the same idea of what long means. We can pretty reliably decide this by looking at the platform we are running on in .NET, though. We are already providing internally booleans for IsWindows and Is32Bit here https://github.com/pythonnet/pythonnet/blob/master/src/runtime/runtime.cs#L106-L109.

Would this method get caught out if, for whatever reason, someone is using CPython compiled with 64bit longs on Win64 or CPython compiled with 32bit longs on 64bit Linux?

If you managed to compile a program that messed up, it will not be able to reliably interact with anything else on the same system. This is an ABI thing, it's not something a user can just decide.

/edit: Note, that this is a completely different question than asking for a 32bit vs 64bit program on a given system. All operating systems that I know of have separate variants of all relevant libraries compiled in the respective fashion, but sizeof(long) is consistent in each of those environments individually.

@Cronan
Copy link
Contributor

Cronan commented Sep 26, 2019 via email

@filmor
Copy link
Member

filmor commented Sep 26, 2019

Yes, and the correct P/Invoke signature can be decided by looking at the IsWindows and Is32Bit values. You wouldn't be able to boot up a .NET VM (or load a libpython in case you're embedding) with non-matching bitness, so drawing those values from .NET will lead to the same result with much less work.

@jmlidbetter
Copy link
Contributor Author

Fixed in PR #961

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants