我正在用 C 编写一个应用程序,它可以在运行时通过模块/共享对象/DLL 进行扩展。这些模块可能会使用现有程序的 API,但也可能会提供新功能供以后加载的模块使用,因此模块之间存在相互依赖的可能性。
我目前在 Linux 下的做法是让每个模块都定义一个 depends() 函数,该函数返回它所依赖的其他模块名称的列表。这样,我就可以自行编译和链接每个模块,使用 dlopen() 和 RTLD_LAZY 加载模块,首先解决其依赖关系,然后使用 RTLD_GLOBAL 完全加载它。这工作得很好并且完全符合我的要求。它还允许我用不同版本替换一个模块,而无需重新编译依赖它的所有其他模块。
将其移植到 Windows 时会出现实际问题。首先,我还没有找到任何方法来链接 DLL,除非已经为其提供所有依赖项的导出符号表。有没有我忽略的?
其次,Windows API 中的 LoadLibraryEx 似乎无法执行任何延迟加载,因为它没有让我处理依赖项,而是继续并在返回之前自行加载所有引用的 DLL。因为我想在将来实际加载模块之前也执行版本检查,所以这根本不是我想要的。有什么办法可以避免这种行为?
第三个奇怪的事情是,如果不重新编译依赖它的所有其他模块,我就无法替换 DLL。它有时确实有效,但通常会发生疯狂的事情或程序段错误。
甚至可以在 Windows 上编写这样的模块化应用程序吗?非常感谢任何建议或不同的方法!
更新:只是为了澄清我的模块如何在 Linux 上使用彼此的功能(我希望在 Windows 上也有):每个模块只返回另一个模块的名称想从所描述的 depends() 函数中调用函数并包含其 header ,然后直接在代码中调用使用的函数而不进行任何包装。这是可行的,因为 Linux 不要求您在链接时为共享对象解析所有符号。
最佳答案
您可以手动导出所有函数(使用 __declspec(dllexport))并使用 GetProcAddress 加载它们。在这种情况下,您需要知道每个函数的签名,并且仅限于 C 函数,但这是可行的。如果你编译这两个模块,你的 C 函数也可以返回 C++ 类,稍后会详细介绍。使用 GetProcAddress 和 LoadLibrary 使模块完全独立。基本上,您需要手动进行链接,但据我了解,这就是您在 Linux 上所做的,对吧?
LoadLibary 仅加载库所依赖的库,因此请确保它们不会相互加载。它们要么是真正独立的,要么不是,如果处理得当,更改一个库不会强制重新编译另一个库(因为您没有将它们链接在一起)。
一个好主意是使用类似 COM 的东西,因此让您的每个库都返回一个接口(interface),而不是单独的函数。这样,您可以简单地加载整个 DLL 并将它们轻松链接在一起(传递 DLL -> 传递对象)。查查XPCOM和COM,其实很容易做到。
关于c - Windows 上带有 DLL 的动态模块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1181991/
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co