2016-02-24 4 views
1

В настоящее время я работаю над визуальным редактором для создания конечных машин. Ядром является C++, поскольку встроенный FSM будет запускаться в игре. Редактором является C#. Мне удалось получить оболочку CLI, чтобы я мог построить все, что мне нужно, на стороне C#. Последнее, что я пытаюсь сделать, - это предоставить шаблонный шаблон для C#.выставлять C++/CLI templated wrapper в C#

Я начал с создания управляемого класса:

template <typename T> 
public ref class TestTemp 
{ 
private: 
    ClassToWrap<T>* m_val; 
public: 

    TestTemp(T val) : 
    { 
     m_val = new ClassToWrap<T>(); 
    } 
} 

Тогда, поскольку шаблоны генерируются во время компиляции, я принуждая поколение типа с специализации шаблона.

template ref class FSMWrapper::TestTemp<float>; 

Я пытался специализация в нескольких местах, CPP, заголовке, а также в основном только в случае, я даже попробовал конкретный экземпляр в основном, как это:

FSMWrapper::TestTemp<float> t(10.0f); 

Я даже пытался явно скажите экспортировать символ, как я бы делал в обычном C++, но компилятор жалуется, что я не могу сделать это с управляемым типом.

После этого мне не удалось получить символ в пространстве имен C# (все остальное появляется, поэтому да, обертка работает так, как ожидалось).

Также, если я удаляю шаблон в оболочке и просто назову его TestTempFloat и принудительно создаю экземпляр float, он работает.

public ref class TestTempFloat 
{ 
private: 
    ClassToWrap<float> m_val; 
public: 

    TestTempFloat(float val) : 
    { 
     m_val = new ClassToWrap<float>(); 
    } 
}; 

Что я пытаюсь сделать, возможно ли это? По googling вокруг выглядит так, как есть, но люди просто говорят, оберните его в CLI-тип и заставьте генерировать символы. Если возможно, что я делаю неправильно?

Если это невозможно, мне просто нужно будет сделать специализированные обертки вручную, но не очень, но я знаю, что это работает.

Я также попытался обернуть его в родовом формате вместо шаблона, но тогда я не могу подавать типовой тип T в качестве типа шаблона.

PS: Я знаю, что для освобождения памяти нет деструктора, это всего лишь фиктивный тест, чтобы сохранить пример коротким.

ответ

1

Как вы уже видели, управляемые шаблоны не доступны за пределами сборки, где они расположены. В основном идея состоит в том, чтобы разоблачить управляемый шаблон как общий интерфейс, который может быть отправлен через границы сборок.

Так что в вашем случае, если вы хотели бы создать ITestTemp, что-то вроде этого ...

generic<typename T> public interface class ITestTemp 
{ 
    public: 
    TestTemp(T val); 
} 

То есть интерфейс, который вы будете экспортировать через сборки.Теперь вы должны преобразовать управляемый шаблон в этот общий интерфейс для этого вы можете использовать наследование, что-то со следующей подписью (внутренних органов опущенные для простоты)

templace<typename T> ref class TestTemp : ITestTemp<T>

После того как вы, что теперь вы должны будете выполните «работу компилятора» (что обычно просто автоматически обрабатывается для обычного шаблона C++), чтобы он мог конвертировать между двумя так сказать. Таким образом, вам придется создать фабричный метод, который создаст конкретные экземпляры, которые вы ищете. Это будет выглядеть так:

public ref class TestTempFactory 
{ 
    public: 
    generic<typename T> static ITestTemp<T>^ Create() 
    { 
     if (T::typeid == String::typeid) 
     { return (ITestTemp<T>^) gcnew TestTemp<String>(); } 
     //more cases as needed... 
    } 
} 

Надеюсь, это объяснит это достаточно хорошо, если не сообщите мне.

+0

Привет, спасибо! Я не знал об интерфейсе thingy, я новичок в C# и совершенно новый для CLI. Он выглядит интересным, и мне нравится немного лучше, чем макрос. Завтра я уйду и расскажу, как это происходит. Спасибо. –

+0

Если вы новичок в C++/CLI, я бы порекомендовал собирать «C++/CLI in Action» от Nishant Sivakumar. Вот где я узнал трюк, который я опубликовал, и это самый полезный ресурс C++/CLI, к которому я пришел. –

+0

Я пытаюсь понять и реализовать этот подход, грубо говоря, все имеет смысл. Единственное, чего мне не хватает, - это когда фабрика вступает в игру? Мне нужно будет напрямую позвонить на завод прямо с C#? Я не буду создавать экземпляр типового типа напрямую. Верный? –

2

Если вы реализуете полноценный подкласс класса шаблонов, это должно сделать трюк. Вам нужно будет реализовать все конструкторы, но как сквозной путь к конструкторам базового класса; нет фактического кода.

public ref class TestTempFloat : TestTemp<float> 
{ 
    TestTempFloat(float val) : TestTemp(val) { }; 
}; 

Если у вас есть много из них, вы могли бы использовать препроцессор:

#define IMPLEMENT_TESTTEMP(namesuffix, type) \ 
public ref class TestTemp ## namesuffix : TestTemp<type> \ 
{ \ 
    TestTemp ## namesuffix(type val) : TestTemp(val) { }; \ 
}; 

IMPLEMENT_TESTTEMP(Float, float) 
IMPLEMENT_TESTTEMP(Double, double) 
IMPLEMENT_TESTTEMP(Int, int) 
+0

Привет, да, это похоже на решение, которое у меня есть сейчас, я не наследовал его, а просто имел экземпляр, специализированный с типом. У меня не так много типов, около 6, но все еще довольно немного кода плиты котла. Я на самом деле не думал о макросе, я не супер поклонник макроса только потому, что немного трудно читать, но, скорее всего, лучше, чем скопировать вставленный код и просто изменить тип. Благодаря! Я попробую метод интерфейса из @Chiune, если я не смогу заставить его работать, я пойду с определением. Между тем, большой палец вверх! –

+0

Не знаете, какие у вас есть предпочтения, но в среде .NET, где нет макромагии, чтобы полагаться на шаблоны T4, вместо этого используются для этого типа задачи, см. [Пошаговое руководство: создание кода с использованием текстовых шаблонов] (https: // msdn .microsoft.com/EN-US/библиотека/dd820614.aspx). Так как вы работаете над C++/CLI, вы можете пойти в любом направлении, хотя T4 чище и легче читать, чем макросы. –