我要做的是能够使用托管代码中的相同方法针对本机DLL的两个版本进行编译。
例如,这将是我的原生方法签名:
__declspec(dllexport) void MyClass::NativeFoo(const TCHAR* txt)
它编译为接受一个版本中的char*
和另一个版本中的wchar*
。
pInvoke签名如下所示:
[DllImport("Native.dll")]
private static extern void NativeFoo(string txt);
为了能够控制pInvoke调用使用的CharSet
,我使用以下方法:
internal static void SetUnicodeMode(bool state)
{
MethodInfo m = typeof(ManagedFoo).GetMethod("NativeFoo", BindingFlags.NonPublic | BindingFlags.Static);
object[] atts = m.GetCustomAttributes(typeof(DllImportAttribute), false);
DllImportAttribute dllatt = (atts[0] as DllImportAttribute);
dllatt.CharSet = state ? CharSet.Unicode : CharSet.Ansi;
}
我在托管程序集启动时调用此方法(此时我知道是否需要使用unicode或mbcs)。
该方法不会抛出任何异常,但它也不会更改pInvoke调用使用的CharSet
。我做错了什么?
答案 0 :(得分:2)
这不起作用。 CLR将创建自己的[DllAttribute]实例,它不会使用你的。用于属性构造函数参数的值存储在程序集元数据中,您无法更改该数据。
前进的唯一合理方法是使用具有不同名称的两个声明。使用属性的EntryPoint属性将它们映射到相同的导出函数。否则你不清楚用什么触发器来选择一个触发器,实际的DLL当然也必须是不同的。这是非常不寻常的,当您使用不同的编译器设置重建DLL时,TCHAR只是一个不同类型的字符。特别是UNICODE和_UNICODE #defines。没有任何可以想象的理由仍然使用8位字符,或TCHAR,这是上个世纪。这里有一个健全性检查。