题
问题(简化,以使事情更清楚):
-
1.有一个静态地联静态的。lib,有一个函数增量:
extern int CallCount = 0;
int TheFunction()
{
void *p = &CallCount;
printf("Function called");
return CallCount++;
}
2.静态的。lib是联成一个管理C++/CLI managed.dll 包裹该函数将方法:
int Managed::CallLibFunc()
{
return TheFunction();
}
3.测试的应用程序具有参考managed.dll 并创建了多个领域调用C++/CLI包装:
static void Main(string[] args)
{
Managed c1 = new Managed();
int val1 = c1.CallLibFunc();
// value is zero
AppDomain ad = AppDomain.CreateDomain("NewDomain");
Managed c = ad.CreateInstanceAndUnwrap(a.FullName, typeof(Managed).FullName) as Managed;
int val2 = c.CallLibFunc();
// value is one
}
问题:
基于什么我读至关重要的。净Vol1CLR的盒子,我希望val2是零,因为一个全新的复制的管理。dll/静态的。lib装载时CreateInstanceAndUnwrap。我误解发生了什么事?静态图书馆似乎并不尊重程序域的界限,因为它不受管理的代码。有没有办法绕过这个问题比其他通过创建一个全新的工艺的实例,管理?
非常感谢大家!
其他提示
之后你打电话
Managed c1 = new Managed();
你的managed.dll 包装物将载入主要的应用程序域的您应用程序。直到它会在那里域托管的东西从静态的。lib将与其他领域。而不是建立独立的过程中,你只是需要确保(在每个呼叫),managed.dll 未载入任何应用领域。
比较与
static void Main(string[] args)
{
{
AppDomain ad = AppDomain.CreateDomain("NewDomain");
Managed c = ad.CreateInstanceAndUnwrap(a.FullName, typeof(Managed).FullName) as Managed;
int val2 = c.CallLibFunc();
// Value is zero
AppDomain.Unload(ad)
}
{
AppDomain ad = AppDomain.CreateDomain("NewDomain");
Managed c = ad.CreateInstanceAndUnwrap(a.FullName, typeof(Managed).FullName) as Managed;
int val2 = c.CallLibFunc();
// I think value is zero
AppDomain.Unload(ad)
}
}
`
重要,并且:如果你只是添加一条线JIT编译器的负载managed.dll 和魔法消失。
static void Main(string[] args)
{
{
AppDomain ad = AppDomain.CreateDomain("NewDomain");
Managed c = ad.CreateInstanceAndUnwrap(a.FullName, typeof(Managed).FullName) as Managed;
int val2 = c.CallLibFunc();
// Value is zero
AppDomain.Unload(ad)
}
{
AppDomain ad = AppDomain.CreateDomain("NewDomain");
Managed c = ad.CreateInstanceAndUnwrap(a.FullName, typeof(Managed).FullName) as Managed;
int val2 = c.CallLibFunc();
// I think value is one
AppDomain.Unload(ad)
}
Managed c1 = new Managed();
}
如果你不想要取决于这种线,您可以创建一个包装ManagedIsolated.dll 将参考managed.dll 并将使每一个呼叫中单独域具有域卸载之后的呼吁。主要应用程序将仅仅取决于ManagedIsolated.dll 类型和Managed.dll 不会被载入主要的应用领域。
这看起来像一个伎俩,但可能是它将是有用的人。`
在短期,也许。应用程序域是一个纯粹的管理概念。当一个程序域的实例,它没有地图在新的副本的基础Dll,它可以重复使用的代码已经在存储器(例如,你不会希望它加载新的副本所有的系统。 集会,对吗?)
在管理世界所有静态的变量范围的通过程序域,但正如你指出这并不适用于不受管理的世界。
你可以做一些事情复杂,部队负荷的一个独特的managed.dll 每个应用领域,这将导致一个新版本的静态lib被带。例如,也许使用的组件。载有一个字节列会的工作,但我不知道如何CLR会试图处理的冲突的类型,如果同组件装载的两倍。
我不认为我们得到的实际问题在这里 看看这DDJ的文章.
默认值的加载程序优化属性是SingleDomain,其中"导致域载入一个私人复制的每个必要组件的代码"。即使它是一个多领域值"每域始终保持一个独特的静态复制领域"。
'managed.dll'为(正如其名称所暗示的)是管理大会。代码在静态的。lib已静态汇编(以IL代码)成'managed.dll',所以我希望同样的行为如Lenik的期望。...
...除非静态的。lib是一个静态的出口库不受控DLL。Lenik说不是这种情况,所以我还不确定怎么在这里。
这些都是最好的两篇文章我发现的主题
- http://blogs.msdn.com/cbrumme/archive/2003/04/15/51317.aspx
- http://blogs.msdn.com/cbrumme/archive/2003/06/01/51466.aspx
重要的部分是:
空中航线管理局的基于静态领域是处理-全球性的。这些限制为标量和价值的类型,因为我们不想允许对象的流血跨域的界限。这将导致各种各样的问题,特别是在程序域卸载。一些语言,如ILASM和MC++使其方便的定义空中航线管理局的基于静态的领域。大多数语言不这样做。
好,如果你要控制的代码。lib,我想试试
class CallCountHolder {
public:
CallCountHolder(int i) : count(i) {}
int count;
};
static CallCountHolder cc(0);
int TheFunction()
{
printf("Function called");
return cc.count++;
}
因为他说,空中航线管理局的基于静态领域是有限的标量和价值的类型。Int阵列可能还会的工作。