main icon indicating copy to clipboard operation
main copied to clipboard

ctypes doesn't work on Mono (OSX/Linux)

Open ironpythonbot opened this issue 11 years ago • 0 comments

The ctypes module doesn't work on OSX or Linux, through Mono. There is a discussion on the mailing list about this, which I reproduce here for tracking purposes. I'm not sure about the calloc call, perhaps Marshal.AllocHGlobal should be used instead, which Mono supports (I believe). And the symlink solution doesn't seem like the right way to fix this. Ideally there should be no extra setup required.

I looked into the ctypes on mono problem a bit (MONO_LOG_LEVEL=debug mono ipy.exe is helpful here). There seem to be three issues:

  1. libdl.so is libdl.dylib on OSX and there is no dllmap that does this automatically on Mono. It checks for libdl.so.dylib and a few other places but not libdl.dylib. This can be fixed by creating a symbolic link or changing the DLLImport to libdl without the ".so". Unfortunately the latter approach breaks breaks linux support. So I just created this symlink by hand, which is not ideal.

  2. On linux, it seems that RTLD_NOW (2) should be passed to the dlopen call. (See http://www.mail-archive.com/[email protected]/msg30407.html ). Without this import ctypes works on OSX but not linux, with it things seem to work on both platforms.

  3. LocalAlloc needs a posix equivalent. I added a calloc(1, size), which seemed to do the trick. I'm not expert here, I assume some of the other public methods should be ported too?

With these changes basic libc calls, like abs(), work on windows, osx, and linux. Lots stuff doesn't work. Printf gives one character everywhere and segfaults on linux, but this seems to be the general state of ctypes support even on Windows. Unfortunately fcntl through ctypes also doesn't seem to work, which is why I was looking into ctypes to start with.

Below are my changes to NativeFunctions.cs, which are a partial solution at best.

    // unix entry points, VM needs to map the filenames.
    [DllImport("libdl.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    private static extern IntPtr dlopen([In] string filename, [In] int flags);





    [DllImport("libdl.so", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    private static extern IntPtr dlsym([In] IntPtr handle, [In] string symbol);





    [DllImport("libdl.so")]
    private static extern IntPtr calloc(uint nelem, IntPtr size);





    // Required for Unix not OSX.
    private const int RTLD_NOW = 2;





    public static IntPtr LoadDLL(string filename, int flags) {
        if (Environment.OSVersion.Platform == PlatformID.Unix ||
            Environment.OSVersion.Platform == PlatformID.MacOSX) {
            return dlopen(filename, RTLD_NOW);
        }
        return LoadLibrary(filename);
    }





    [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
    public static IntPtr Calloc(IntPtr size) {
        if (Environment.OSVersion.Platform == PlatformID.Unix ||
             Environment.OSVersion.Platform == PlatformID.MacOSX) {
                 return calloc(1, size);
        }
        return LocalAlloc(LMEM_ZEROINIT, size);
    }

Work Item Details

Original CodePlex Issue: Issue 27471 Status: Active Reason Closed: Unassigned Assigned to: Unassigned Reported on: Jun 10, 2010 at 6:33 PM Reported by: tristanz Updated on: Sep 15, 2013 at 10:01 PM Updated by: alefnula

ironpythonbot avatar Dec 09 '14 17:12 ironpythonbot