我使用C ++ / CLI包装C库,以便可以通过C#方式轻松地从C#中使用C库。
此库中的某些功能用于将值放入容器中。 C中没有泛型,因此每种类型CLIB_SetBool(BOOL值),CLIB_SetInt(int值),CLIB_SetString(char * string)等都存在函数。
为了更容易使用C#,我创建了一个带有System :: Object的Set函数。
我有两个相关的问题:
使用my方法,您如何在System :: Object类型上使用switch语句来调用正确的CLIB_Setxxxx函数。 [typeid仅用于非托管代码,我似乎无法使用GetType。]
有没有更好的方法来包装这些函数,比如使用Generic? [我开始使用模板专业化但后来意识到C#没有看到模板。]
感谢。
修改
如何实现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失败,显然案例无效。怎么解决?
答案 0 :(得分:2)
你可能比使用代表字典更糟糕,按类型键入(对不起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 :(得分:2)
如下所示的一些重载...
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进行适当的编组 - &gt; char *转换,但你明白了。
已修改为包含类型检测
答案 2 :(得分:1)
我不能使用开关,因为在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
}