std_vector.i неправильно переносит унаследованные классы

0

В C++ у меня есть класс ("BaseClass") и класс ("ClassA"), который наследуется от BaseClass. Я использую SWIG 3.0.2 для переноса моего материала C++ на С#, и я использую "std_vector.i", чтобы включить функцию "Список" в моем приложении С#.

В функции C++ "CallCS" я создаю список из двух элементов: первый из них - класс BaseClass, второй - ClassA. Список доступен для приложения С# через функцию обратного вызова. Файл интерфейса показывает, как я завершаю список.

Однако, итерации через список в приложении С#, я не могу получить доступ к элементу ClassA как к элементу ClassA, хотя он наверняка является элементом ClassA (я просто не могу его каким-либо образом отличить). Я могу получить доступ к нему только так, как если бы это был объект BaseClass.

Может ли кто-нибудь сказать мне, если я что-то пропущу?

Вот мой C++.h файл:

#include <vector>

class BaseClass
{
public:
    int m_x;
    BaseClass(int x): m_x(x) {}
    int GetX() { return m_x; }
};

class ClassA : public BaseClass
{
public:
    int m_y;
    ClassA(int x, int y) : BaseClass(x), m_y(y) {}
    int GetY() { return m_y; }
};

typedef std::vector<BaseClass*> BaseListType;

class Receiver
{
public:
    virtual void CallBack(BaseListType& list) {}
};

class Sender
{
public:
    Receiver* m_receiver;
public:
    Sender(Receiver* receiver) : m_receiver(receiver) {}
    void CallCS()
    {
        BaseListType list;
        list.push_back(new BaseClass(0));
        list.push_back(new ClassA(1, 2));
        m_receiver->CallBack(list);
    }
};

Вот мой файл интерфейса:

%module(directors="1") example

%include <std_vector.i>

%feature("director") Receiver;

%{
#include "example.h"
%}

%include "example.h"

%template(BaseListType) std::vector<BaseClass*>;

Вот мой файл С#:

using System;
using System.Collections.Generic;
using System.Linq;

public class runme
{
    class Subscriber : Receiver
    {
        public override void CallBack(BaseListType list)
        {
            Console.WriteLine("------------------------ CallBack ...");
            Console.WriteLine("  Expectation:");
            Console.WriteLine("    First elem:  BaseClass");
            Console.WriteLine("    Second elem: ClassA");
            Console.WriteLine();
            var classalist = list.Select(x => x as ClassA).Where(x => x != null).ToList();
            Console.WriteLine("  Count(ClassA) = " + classalist.Count() + ":");
            foreach (BaseClass elem in list)
            {
                Console.WriteLine("    Is BaseClass: " + (elem is BaseClass) + " ... Is ClassA: " + (elem is ClassA));
            }
            Console.WriteLine("------------------------ CallBack done");
        }

        public void Run() 
        {
            Sender s = new Sender(this);
            s.CallCS();
        }
    }

    static void Main() 
    {
        Subscriber s = new Subscriber();
        s.Run();
    }
}
  • 0
    Разве это не проблема C ++ (base * = производная *), а не swig? В идеале у вас должен быть виртуальный BaseClass :: GetY (). Или добавьте чистый виртуальный тип () в BaseClass и сделайте, если type () == THIS / THAT в вашем коде приложения (Yikes! Я знаю). Избегайте динамической борьбы, которую мы (по крайней мере, я) всегда переживаем. Не знаю, как происходит приведение типов в C #.
  • 0
    Похоже, ваше предложение .Where () исключает элемент BaseClass, потому что x в качестве класса A будет возвращать null, когда он является объектом типа BaseClass, поэтому он никогда не попадет в список.
Показать ещё 2 комментария
Теги:
class
swig

1 ответ

0

Не могу проверить здесь, но добавление virtual ~BaseClass() {} в BaseClass, вероятно, сделает это.

  • 0
    Спасибо за ваш ответ. К сожалению, это не решило мою проблему. Однако я нашел решение - см. Мой комментарий к самбхе.
  • 0
    Отлично. Вы должны поместить свой комментарий в ответ, который показывает, как вы применили технику из этого поста, а затем принять свой ответ, чтобы он был закрыт. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню