On Tue, Aug 10, 2010 at 9:56 PM, David Cournapeau <[email protected]> wrote:
> On Fri, Aug 6, 2010 at 1:55 PM, Carl Witty <[email protected]> wrote:
>
>> For IronPython running under Microsoft's .NET implementation for
>> Windows, as far as I know there are no problems with C++/CLI. For
>> IronPython running under Mono on non-Windows platforms, C++/CLI
>> doesn't help at all; there are no implementations of C++/CLI on
>> non-Windows platforms and no effort toward making an implementation.
>> So the purpose of a C# backend would be to support Mono.
>
> I would think that it would also help for a jython backend, as there
> is no equivalent to C++/CLI in the java land AFAIK, and changing from
> C# to java back in cython should be much easier.
It certainly seems likely that a C# backend would be a much better
starting point for a Jython port than a C++/CLI backend. (I'm not
familiar enough with Jython internals or with the JVM->C interface to
be more precise, though.)
> For people who are not so familiar with C++/Cli, could you expand a
> bit more on the choice of C++/CLI vs C# as a first step ? The "extern"
> part sounds logical (a VM like the CLR or the JVM has strong strong
> ABI constraints), but the exception part not so much.
Sure. The issue with exceptions is almost trivial, but still important.
According to the Mono P/Invoke documentation, P/Invoke is for talking
to C functions. If a function throws a C++ exception, it wasn't a C
function. And in particular, under Mono, if you P/Invoke a function
that throws a C++ exception, very bad things happen; the exception
can't be caught by managed code, and probably your application
crashes.
So the Cython construct:
cdef extern from "some_file.h":
cdef int foo() except +
(which tells Cython to catch any C++ exceptions thrown by foo() and
turn them into Python exceptions) can't be implemented only in managed
code and P/Invoke; you need at least a little C++ wrapper for each
such function that catches all exceptions and returns them another
way.
> Also, what does
> C++/Cli buys you instead of pure C or C++ (through p/invoke) ?
In a way, C++/CLI is like Cython.
Cython is a sort of mixture of C and Python, and you can interoperate
(almost) seamlessly with either language from Cython code. Similarly,
C++/CLI is a mixture of C++ and the CLI, and you can interoperate
(almost) seamlessly with either from C++/CLI code. This makes it a
very nice target language for Cython: the C-like code compiles
straight to C++, and the Python-like code compiles fairly nicely to
the CLI side (with a lot of help from the IronPython implementation).
For example, IronPython objects are garbage collected; you don't have
to do anything special to support garbage collection (on CLI objects)
in C++/CLI. The "raise" statement translates to "throw";
"try:/except:" translates to "try/catch". (Of course, having
try:/except: translate to try/catch has a downside as well; it
increases the differences between the CPython and IronPython backends
of Cython, which makes it harder to share code between them.)
> CLI is
> gc aware, right ? I am also curious about the differences between
> C++/CLI vs p/invoke (the latter having an equivalent in the java),
I explained above why C++/CLI might be a particularly nice language if
you needed to interface to (say) both C and C#. That's not really so
important for a compiler, though... you can tolerate some ugliness in
the output code, since that's all hidden inside the compiler. (Cython
does fine generating C, even though C has no built-in Python support.)
In my opinion, the major advantage of C++/CLI over C# with P/Invoke is
that C++/CLI has a working C++ header file parser. This means that we
can keep the current Cython semantics, where users describe to Cython
the API (rather than the ABI) of the library they're trying to call;
then Cython generates C, C++, or C++/CLI code that conforms to this
API, and the compiler handles the rest.
If the user did specify the ABI, then we could make Cython generate C#
code with P/Invoke to wrap C functions. (Wrapping C++ with P/Invoke
has multiple issues; the exception thing I already described,
non-portable name mangling, non-portable object layout across
compilers... I don't think that's ever likely to work.) That would be
a lot of new code, though. With C++/CLI, we can generate the exact
same code from the C-like portions of Cython that we do for C or C++.
In another sense, C++/CLI adds no capabilities over C# with P/Invoke,
because by default it compiles to the same bytecode language. In
fact, you can use the free Reflector decompiler to decompile
C++/CLI-generated bytecode into C# source. (I haven't tried
recompiling the C#, but it looks approximately legal.) It's sort of
interesting; you get a strange mixture of low-level pointer arithmetic
code and normal high-level code. If you compile "errno", it
decompiles to "*(_errno())". Accessing the .st_size member of a
struct stat decompiles back to "*((int*) (&_stati + 20))".
(I mentioned before that you couldn't deal with C++ exceptions using
P/Invoke. That's true for Mono, but it's not an issue for C++/CLI,
because Microsoft's C++ uses the same exception mechanism as the CLI.)
Carl
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev