针对混合平台(32、64)进行编译并引用运行时解析的 32 或 64 位 DLL
在windows 32位或64位下使用VS2010。 我们的 C# 应用程序调用与非托管 DLL 接口的第 3 方 DLL(托管)。 第 3 方 DLL API 在 32 或 64 位中看起来相同,尽管其下方链接到 32 或 64 位非托管 DLL。
我们希望我们的 C# 应用程序在 32 位或 64 位操作系统上运行,理想情况下它会自动检测操作系统并加载适当的第 32 方 DLL - 通过一个测试环境的简单工厂类。因此,最巧妙的解决方案是包含以下内容的运行时文件夹: OurApp.exe 3rdParty32.DLL 3rdPartyUnmanagement32.DLL 3rdParty64.DLL 3rdPartyUnmanagement64.DLL
但是,托管 3rdParty 32 和 64 dll 的接口是相同的,因此不能在同一个 VS2010 项目中引用两者:添加第二个时,会显示警告三角形,并且它不会被引用。
我唯一的答案是创建两个额外的库 DLL 项目来引用 3rdParty 32 和 64 Dll?所以我最终会做出这样的项目安排: 项目 1:构建 OurApp.exe,动态创建项目 2 或项目 3 的对象。 项目 2:构建引用 3rdParty32.dll 的 OurApp32.DLL 项目 3:构建引用 3rdParty64.dll 的 OurApp64.DLL
Using VS2010 under windows 32 or 64 bit.
Our C# app calls a 3rd party DLL (managed) that interfaces to an unmanaged DLL.
The 3rd party DLL API appears identical in 32 or 64 bit although underneath it links to a 32 or 64 bit unmanaged DLL.
We want our C# app to run on either 32 or 64 bit OS, ideally it will auto detect the OS and load the appropriate 32rd party DLL - via a simple factory class which tests the Enviroment. So the neatest solution would be a runtime folder containing:
OurApp.exe 3rdParty32.DLL 3rdPartyUnmanaged32.DLL 3rdParty64.DLL 3rdPartyUnmanaged64.DLL
However, the interface for the managed 3rdParty 32 and 64 dll is identical so both cannot be referenced within the same VS2010 project: when adding the second the warning triangle is shown and it does not get referenced.
Is my only answer to create two extra library DLL projects to reference the 3rdParty 32 and 64 Dlls? So I would end up with this project arrangement:
Project 1: Builds OurApp.exe, dynamically creates an object for project2 or project3.
Project 2: Builds OurApp32.DLL which references 3rdParty32.dll
Project 3: Builds OurApp64.DLL which references 3rdParty64.dll
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
由于您拥有特定于 32 位或 64 位的非托管代码,因此您失去了托管代码能够在运行时 JIT 到任一模式的优势。最简单的方法可能是设置 make 文件来构建应用程序两次,一次用于 64 位,一次用于 32 位,并使用 csproj 文件中的条件部分来引用 32 位或 64 位非托管 DLL。让安装程序安装在安装时找到的适合平台的二进制文件。
Since you have unmanaged code that is 32 bit or 64 bit specific, you lose the advantage of managed code being able to JIT into either mode at runtime. It might be simplest just to set up your make file to build your application twice, once for 64 bit and once for 32 bit, and use conditional sections in the csproj file to reference the 32 bit or 64 bit unmanaged DLLs. Let the installer install the binaries appropriate to the platform as found at install time.
我不能说我以前这样做过,但快速搜索告诉我您可以针对接口进行编程并通过反射动态加载库。
你考虑过这个吗?
I cant say I have done this before but a quick search tells me you can program against an interface and load the library dynamically via reflection.
Have you considered this?
这里有一个想法,应该可以通过自定义构建过程来实现:
让您的项目两次编译为 YourApp32.exe 和 YourApp64.exe,并适当修改引用。然后还使用引导程序 YourApp.exe 创建第三个项目,该项目只会检查系统的位数并加载 YourApp32.exe 或 YourApp64.exe。
当然,这可能只适用于发布版本,因为您实际上使编译时间加倍,这对开发人员来说会很烦人。
Here's an idea, which should be possible by customizing your build process:
Have your project compile twice to YourApp32.exe and YourApp64.exe, modifying the references appropriately. Then also make a 3rd project with a bootstrapper YourApp.exe, which will only check the bit-ness of the system and load either YourApp32.exe or YourApp64.exe.
Naturally, this should probably be done only for release builds, because you effectively double your compile time, which will be annoying for the developers.
一种选择是在工厂中使用反射来在运行时加载正确的第 3 方程序集,并创建正确类的实例,并返回对此的引用。然后,您可以将程序集放在与可执行文件相同的目录中,并在运行时加载正确的程序集,而无需添加项目引用。然而,通常这使用来自另一个程序集的已知基抽象类或接口(通常专门用于保存所需的声明)。听起来你没有这个。
但是,根据第 3 方管理的 DLL 的类型层次结构的复杂性,沿着这条路线可能有一个选项,但需要稍微多做一些工作。
string DoFoo(int a, int b)
的方法将具有类似于委托 string DoFooDelegate(int a, int b)
的委托。如果方法具有相同的签名,您可以对所有这些方法使用单个委托。添加到在第 3 方 DLL 中调用的每个方法的变量之前创建的类集。因此,您的类将具有一组类似于private DoFooDelegate doFoo;
的成员。然后可以是您认为合适的任何访问级别。这是一种非常hacky的方法。如果您有选择,请联系提供 DLL 的第三方,看看是否可以说服他们将与两个 DLL 匹配的抽象类或接口公开到第三个程序集中,然后您就可以引用它,而无需进行所有的处理与代表们。
One option would be to use reflection in your factory to load the corrected 3rd party assembly at run time, and create an instance of the proper class, and return a reference to that. Then you can just put the assemblies in the same directory as your executable, and load the proper one at runtime, without adding a project reference. However, typically this uses either a known base abstract class or interface from another assembly (Typically one devoted to just holding the needed declarations). It does not sound like you have this.
However, depending on the complexity of the type hierarchy of the 3rd party managed DLL, there could be an option along this route, with slightly more work.
string DoFoo(int a, int b)
would have a delegate something likedelegate string DoFooDelegate(int a, int b)
. If methods have the same signature, you can use a single delegate for all of those. Add to your set of classes created before a variable for each method to be called in the 3rd party DLL. So your classes would have a set of members along the lines ofprivate DoFooDelegate doFoo;
. Then can be whatever access level you deem appropriate.This is a very hacky way of doing this. If you have the option, get ahold of the 3rd party supplying the DLLs and see if you can convince them to expose either abstract classes or interfaces matching their two DLLs into a third assembly, then you can reference that, without all of the mucking around with delegates.