1

我想要做的是能够在托管代码中使用相同的方法针对本机 DLL 的两个版本进行编译。

例如,这将是我的本机方法签名:

__declspec(dllexport) void MyClass::NativeFoo(const TCHAR* txt)

它编译为接受char*一个构建和wchar*另一个构建。

pInvoke 签名如下所示:

[DllImport("Native.dll")]
private static extern void NativeFoo(string txt);

为了能够控制CharSetpInvoke 调用使用的,我使用以下方法:

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)。

该方法不会引发异常,但也不会更改CharSetpInvoke 调用使用的方法。我究竟做错了什么?

4

1 回答 1

2

这是行不通的。CLR 将创建自己的 [DllAttribute] 实例,它不会使用您的实例。用于属性构造函数参数的值存储在程序集元数据中,您无法更改该数据。

继续前进的唯一合理方法是使用两个具有不同名称的声明。使用属性的 EntryPoint 属性将它们映射到相同的导出函数。否则非常不清楚您将使用什么触发器来选择另一个触发器,实际的 DLL 当然也必须有所不同。这是非常不寻常的,当您使用不同的编译器设置重建 DLL 时,TCHAR 只是一种不同类型的字符。特别是 UNICODE 和 _UNICODE #defines。没有任何可以想象的理由仍然使用 8 位字符或 TCHAR,那是上个世纪。此处高度指示进行完整性检查。

于 2013-03-16T18:16:21.900 回答