Вызов шаблонной функции C ++ из C # - PullRequest
3 голосов
/ 19 мая 2011

У меня очень ограниченные знания C #. Моя цель - предоставить C ++ dll API моему коллеге по C #. DLL должна быть в C ++ по устаревшим причинам.

Вопрос - Может ли шаблонная функция C ++ (показанная ниже из VS) быть маршалинговой в C #?

class  __declspec(dllexport) Foo
{
public: 
    template <typename T> T* getFoo(T* fooData){return fooData;};
};

Если нет, есть предложения? Должен ли каждый тип, передаваемый в функцию шаблона, иметь свою собственную функцию, чтобы C # мог ее маршалировать?

Ответы [ 3 ]

4 голосов
/ 19 мая 2011

Я думаю, что вам лучше всего написать код на C ++ / CLI .Вы можете предоставить управляемый API, который может использоваться кодом C #, но при необходимости использовать собственный C ++.

4 голосов
/ 19 мая 2011

Вопрос - Может ли шаблонная функция C ++ (показанная ниже из VS) маршалироваться в C #?

Нет. Не существует совместимого двоичного интерфейса от C # до C ++. Вы можете вызывать только экспортированные символы C из C #.

Теоретически, вы можете явно создать экземпляры шаблонов в C ++ DLL, что приведет к тому, что они получат внешние ссылки и записи в таблице символов экспорта. Но искажение имен сделает функции непригодными для всех практических целей. Поэтому лучше всего иметь промежуточный C-совместимый уровень, который вызывает основные функции C ++.

1 голос
/ 03 июня 2011

Итак, через несколько недель я смог запустить что-то и подумал, что поделюсь этим с группой. (Простите за внешний вид псевдокода). Я в основном учил себя C # вместо C ++ / CLI.

Помните вопрос - Может ли шаблонная функция C ++ (показанная ниже из VS) быть маршалинговой в C #?

Моя работа заключается в следующем: сделать маршалированные неуправляемые вызовы C # для функций C ++, которые могут переводить вызовы в метод шаблона.

Вот код:

//C++ code
//C++ Header
class  __declspec(dllexport) Foo
{
    public: 
        template <typename T> T* getFoo(T* fooData){return fooData;};
};

extern "C" __declspec(dllexport) void call_getFoo(Foo* pFoo, void* pfooData, int fooId)
{
    switch(fooId)
    {
        case(ENUM::1) : //Use an enum here for a better switch statement.       
        {   
            //Cast the void pointer to a specific type so the template knows how to use it.
            pFoo->getFoo((*TypeCast*)pfooData);
        break;
        }
    }
}

//C# Code
internal static class UnsafeNativeMethods
{
    const string _dllLocation = "Foo.dll";

    [DllImport(_dllLocation)]
    static public extern void call_getFoo(IntPtr pFoo, IntPtr pfooData, int fooId);           
}

//In a C# method
...
...
//Marshal Up a C# data type to a pointer for C++.
*YOUR TYPE HERE* myType;
int rawsize = Marshal.SizeOf(myType);
IntPtr pfooData = Marshal.AllocHGlobal(rawsize);
Marshal.StructureToPtr(myType,pfooData,true);

//call the C++ dll
UnsafeNativeMethods.call_getFoo(pFoo, pfooData, fooId);

//Convert Ptr Back To myType
myType = (*YOUR TYPE HERE*) Marshal.PtrToStructure(pfooData, typeof(*YOUR TYPE HERE*));
...
...

Надеюсь, это поможет!

...