У меня есть два модуля Perl, которые я хочу выставить как типы объектов C#. Один из них создает объекты другого типа и возвращает его с помощью метода как показано ниже. Я включаю ссылку на Type2.dll в Type1.dll и ссылаюсь на них обоих в C#. Поскольку код показывает, что я могу создать объект Type2 непосредственно из C#, но я не могу возвратить объект Type2, который был создан методом в Type1. Какие-либо идеи?
(Это перекрестно разослано из http://community.activestate.com/forum/return-perl-object-different-perl-class-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;
Поскольку этот вопрос был размещен на community.activestate.com и на него уже был дан ответ, я скопирую ответ оттуда сюда, но сокращу его, потому что он кажется мне слишком длинным.
Основная проблема заключается в том, что в том виде, как вы написали, Type2
не считается типом, и вызов Type2->new()
не является вызовом конструктора (а является вызовом статического метода).
Следующие изменения в вашем коде исправляют это:
package Type2
на package Sample::Type2
. Это делает Type2 типом, а Sample - пространством имен. package Type1
на package Sample::Type1
. use Type2;
на use namespace "Sample";
. Это импортирует Type2 как тип. После этих изменений опубликованный код на C# работает как надо.
Я также обнаружил, что могу создать один такой файл:
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.