2010-04-21 13 views
9

Tengo dos módulos Perl que quiero exponer como tipos de objetos a C#. Uno de ellos construye objetos del otro tipo y lo devuelve utilizando un método como se muestra a continuación. Incluyo una referencia a Type2.dll en Type1.dll y hago referencia a ambos en C#. Como el código muestra que puedo construir un objeto Type2 directamente desde C#, pero no puedo devolver un objeto Type2 que fue construido por un método en Type1. ¿Algunas ideas?Devolver un objeto perl de una clase perl diferente a C# utilizando PerlNET

(Cruz-registrado desde http://community.activestate.com/forum/return-perl-object-different-perl-class-c)

C#:

Type1 obj1 = new Type1(); // Works 
Type2 test = new Type2(); // Works 
Type2 obj2 = obj1.make2(); 
// Fails: System.InvalidCastException: Unable to cast object of type 
// 'PerlRunTime.SV' to type 'Type2' at Type1.make2() 

Perl: Type1.pm

package Type1; 

use strict; 
use Type2; 

=for interface 
    [interface: pure] 
    static Type1(); 
    Type2 make2(); 
=cut 

sub new { 
    my $class = shift; 
    return bless {}, $class; 
} 

sub make2 { 
    my $this = shift; 
    return Type2->new(); 
} 

1; 

Perl: Type2.pm

package Type2; 

use strict; 

=for interface 
    [interface: pure] 
    static Type2(); 
=cut 

sub new { 
    my $class = shift; 
    return bless {}, $class; 
} 

1; 
+0

FYI: Estoy usando el ActiveState Perl Dev Kit 8.2.1, PerlNET y .NET 3.5. – DougWebb

+0

Es mejor agregar esto en su pregunta. – Space

Respuesta

2

Desde este fue publicado en forma cruzada en community.activestate.com y ha sido contestada allí, copiaré la respuesta desde allí hasta aquí, pero la reduciré porque creo que es demasiado larga.

El principal problema es que la forma en que lo escribió, Type2 no se considera un tipo , y llamando Type2->new() no se traduce a una llamada al constructor (pero una invocación de método estático).

Los siguientes cambios en el código de solucionar este problema:

  • En Type2.pm, cambie package Type2 a package Sample::Type2. Esto hace que Type2 sea un tipo y Sample a namespace.
  • En Type1.pm, cambie package Type1 a de manera similar.
  • En Type1.pm, cambie use Type2; por use namespace "Sample";. Esto importa Type2 como tipo.

El código C publicado funciona como se requiere después de estos cambios.

1

También he encontrado que puedo crear un archivo de la siguiente manera:

package Type2; 

=for interface 
    [interface: pure] 
    static Type2(); 
=cut 

require Type2; 


package Type1; 
use Type2; 

=for interface 
    [interface: pure] 
    static Type1(); 
    Type2 make2(); 
=cut 

Entonces mi Type1.pm y archivos Type2.pm son los mismos que antes, pero sin la interfaz de POD. Con esta configuración, plc crea un dll único que incluye ambas clases, y la clase Type1 puede crear y devolver instancias de Type2.

Esto en realidad resultó ser más conveniente para mí, porque mis clases Type1 y Type2 son parte de una biblioteca heredada que deseo poner a disposición del código C# sin hacerles cambios extensos específicos de .NET. Creé un archivo pm para mi ensamblado C#, y dentro de él incluí las definiciones de interfaz para acceder a los métodos heredados de biblioteca y un grupo de métodos específicos .NET para propiedades y conversión de valores de retorno complejos de estructura de datos hash/array a Perl Hashtable y Array/ArrayList estructuras de datos.

Cuestiones relacionadas