On Fri, Aug 6, 2010 at 2:12 AM, Dag Sverre Seljebotn
<[email protected]> wrote:
> My reason for asking is that I looked forward to all the goodies of C#:
> The "dynamic" type with call-site caching when calling methods on pure
> Python objects, and (down the line) builtin support for closures. (I
> don't know how much of that is available in C++/CLI?)

Unfortunately, as far as I can tell "dynamic" is useless for a Cython
backend, because it will use .NET semantics rather than Python
semantics for .NET types.

For example, IronPython represents a Python string as a .NET string --
not a wrapper or a subclass, just a plain .NET string.  Then there's a
bit of magic in the IronPython method lookup code, so that it will
notice if you're looking up a Python method on a .NET string and do
the right thing.  But the magic won't be there in the code generated
for C# "dynamic", so this would fail:

  dynamic s = "a random string";
  dynamic h = s.__hash__();

Cython-generated code will have the same call-site caching as
"dynamic"; we'll just have to generate the code ourselves.  In fact,
there is some of this already in the code I posted; for an untyped
addition, it will generate the following:

A declaration in a "module global variables" class:

  CallSite< Func< CallSite^, Object^, Object^, Object^ >^ >^
__site_op_add_16_14;

This executes once at module load time:

    __site_op_add_16_14 = CallSite< Func< CallSite^, Object^, Object^,
Object^ >^ >::Create(context->CreateBinaryOperationBinder(ExpressionType::Add));

And then to actually do the addition:

  __pyx_t_1 = 
__pyx_globals->__site_op_add_16_14->Target(__pyx_globals->__site_op_add_16_14,
__pyx_v_v1, __pyx_v_v2);

(The 16 and 14 are the line and column number of the addition
operation; I thought this would be nicer than some sort of counter.  I
encoded the operation type in the call site name so you can see what
the call is doing.)

I think it's true that C# supports closures and C++/CLI does not.  I
haven't thought much about the issues here, but I was assuming that
the IronPython backend would implement closures in the same way as the
CPython backend, rather than relying on closure support in the target
language.

> Speaking, hypothetically, about a C# backend, my two preferred options
> for _C_ code are either a) require that an ABI is specified in the
> Cython code (which is backwards-compatible with specifying API), or b) a
> two-stage build to generate C source that generates C# source (using
> offsetof and sizeof etc. to get hold of the ABI).

Option (a) is really annoying for libraries like libc, with a portable
API but wildly varying ABIs.  For example, to wrap the stat() system
call, you would need to deal with the fact that "struct stat" has
different members with different names on different OSes (and OS
versions), and the fact that errno might or might not be provided by

  #define errno (*_errno())

But maybe there are no other libraries like libc; I can't think of
other examples off the top of my head.  I guess that usually if you
want to portably wrap a library, it's because the library
implementation is portable and will have a similar ABI on different
platforms.  And wrapping libc is not so useful, since so much of it is
already provided by Python.

Option (b) is intriguing, and not something I'd considered.  It
doesn't help for "#define errno (*_errno())", but should make it
possible to not write wrappers for struct member access, which would
be a big efficiency advantage.  I'll definitely consider this if I do
end up working on a C# backend.

> Interfacing with C++ would need run-time wrappers, anyway, though...
>
> Anyway, I'm really glad that you have such a good handle on these
> things; I'm really happy Enthought asked you about this, they couldn't
> have got someone better for the task.

Thanks!

Carl
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to