Одиночный метод C ++ / CLI, чтобы обернуть много специфичных для типа функций C - PullRequest
2 голосов
/ 06 января 2011

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

Некоторые функции в этой библиотеке предназначены для помещения значения в контейнер. В C нет обобщений, поэтому для каждого типа существует функция CLIB_SetBool (значение BOOL), CLIB_SetInt (значение int), CLIB_SetString (char * string) и т. Д.

Чтобы упростить использование из C #, я создал одну функцию Set, которая принимает System :: Object.

У меня есть два связанных вопроса:

  1. С моим методом, как бы вы использовали оператор switch для типа System :: Object для вызова правильной функции CLIB_Setxxxx. [typeid предназначен только для неуправляемого кода, и я не могу использовать GetType.]

  2. Есть ли лучший способ обернуть эти функции, например, используя Generic? [Я начал использовать специализацию шаблонов, но потом понял, что C # не видит шаблоны.]

Спасибо.

EDIT

Как мне реализовать void Set (System :: Object ^ value)?

Я хочу сделать что-то вроде:

void MyWrapper::Set(System::Object^ value)
{
 switch(typeid(value))
  {
   case System::Int32:  CLIB_SetInt(MyMarshal<clib_int>(value));    break;
   case System::Double: CLIB_SetInt(MyMarshal<clib_double>(value)); break;
//and so on
}
}

Идентификатор typeid не выполняется для управляемого кода, и, очевидно, случаи недопустимы. Как исправить?

Ответы [ 3 ]

2 голосов
/ 06 января 2011

Как насчет некоторых перегрузок следующим образом ..

ref class CLIB_Wrapper
{
    static void Set(System::Boolean^ value) { CLIB_SetBool(*value); }
    static void Set(System::Int32^ value) { CLIB_SetInt(*value); }
    static void Set(System::String^ value) { CLIB_SetString(*value); }

    static void Set(System::Object^ value)
    {
        System::Type^ type = value->GetType();
        if( type == System::Boolean::typeid )
        {
            Set((System::Boolean^)value);
        }
        else if( type == System::Int32::typeid )
        {
            Set((System::Int32^)value);
        }
        else if( type == System::String::typeid )
        {
            Set((System::String^)value);
        }
    }
};

Очевидно, что вам понадобятся некоторые преобразования с соответствующим маршаллингом для преобразования String -> char *, но вы поймете идею.

Отредактировано для включения обнаружения типа

2 голосов
/ 06 января 2011

Вы могли бы сделать хуже, чем использовать словарь делегатов с ключами по типу (извините за синтаксис C #, давно я не делал C ++ / CLI).Разумеется, внутри каждого делегата вы делаете свой фактический вызов соответствующей функции C.

public delegate void CLIBDelegate(object);


// handlers for types that will call the appropriate CLIB_XXX function:
public void CLIB_int(object _obj);
public void CLIB_string(object _obj);
// etc...


// Our dictionary:
Dictionary<System.Type, CLIBDelegate> dict = new Dictionary<System.Type, CLIBDelegate>();
dict[typeof(System.Int32)] = CLIB_int;
dict[typeof(System.string] = CLIB_string;
// etc...


// your set function
void Set(Object _object)
{
    if(dict.ContainsKey(_object.GetType())
        dict[_object.GetType()](_object);
} // eo Set
1 голос
/ 06 января 2011

Я не могу использовать переключатель, потому что, похоже, не существует интегрального представления типа для управляемого кода, как в C ++.

Следующие работы.

void MyWrapper::Set(System::Object^ value)
{
  if (value->GetType() == System::Int32::typeid)
  {
      CLIB_SetInt(MyMarshal<clib_int>(value));
  }  
  else if ((value->GetType() == System::Double::typeid)
  {
      CLIB_SetDouble(MyMarshal<clib_double>(value));
  }
//etc
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...