Возврат объекта Perl из другого класса Perl в C# с помощью PerlNET

У меня есть два модуля Perl, которые я хочу представить как типы объектов для C#. Один из них создает объекты другого типа и возвращает их, используя метод, как показано ниже. Я включаю ссылку на Type2.dll в Type1.dll и ссылаюсь на них обоих в C#. Как видно из кода, я могу создать объект Type2 непосредственно из C#, но не могу вернуть объект Type2, созданный методом в Type1. Есть идеи?

(Это перекрестная публикация с 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()

Перл: 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;

Перл: Type2.pm

package Type2;

use strict;

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

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

1;

person DougWebb    schedule 21.04.2010    source источник
comment
К вашему сведению: я использую ActiveState Perl Dev Kit 8.2.1, PerlNET и .NET 3.5.   -  person DougWebb    schedule 21.04.2010
comment
Лучше добавить это в свой вопрос.   -  person Space    schedule 26.04.2010
comment
Ссылка (фактически) не работает - Отказано в доступе.   -  person Peter Mortensen    schedule 21.08.2019


Ответы (2)


Поскольку это было опубликовано на community.activestate.com и там был дан ответ, я скопирую ответ оттуда сюда, но урежу его, потому что считаю его слишком длинным.

Основная проблема заключается в том, что в том виде, как вы это написали, Type2 не считается типом, а вызов Type2->new() не преобразуется в вызов конструктора (а вызывается статический метод).

Следующие изменения в вашем коде исправляют это:

  • В Type2.pm измените package Type2 на package Sample::Type2. Это делает Type2 типом, а Sample пространством имен.
  • В Type1.pm аналогичным образом измените package Type1 на package Sample::Type1.
  • В Type1.pm измените use Type2; на use namespace "Sample";. Это импортирует Type2 как тип.

Опубликованный код C# работает должным образом после этих изменений.

person Timwi    schedule 10.05.2010

Я также обнаружил, что могу создать один файл следующим образом:

package Type2;

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

require Type2;


package Type1;
use Type2;

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

Тогда мои файлы Type1.pm и Type2.pm такие же, как и раньше, но без интерфейса POD. При такой настройке plc создает единую dll, включающую оба класса, а класс Type1 может создавать и возвращать экземпляры Type2.

На самом деле это оказалось более удобным для меня, потому что мои классы Type1 и Type2 являются частью устаревшей библиотеки, которую я хочу сделать доступной для кода C#, не внося в них значительных изменений, специфичных для .NET. Я создал один файл pm для своей сборки C#, и в него я включил определения интерфейса для доступа к устаревшим библиотечным методам и кучу специфичных для .NET методов для свойств и преобразования сложных возвращаемых значений структуры данных хэша/массива Perl в Структуры данных Hashtable и Array/ArrayList.

person DougWebb    schedule 10.05.2010