语法
在Unity使用DllImport,导入C++写的dll后,如果Unity Editor停止运行,导入的dll还被引用住,如果要修改dll,就必须关闭Unity,导致了调试很耗时。
追踪DllImport的代码,可以发现,对应函数在第一次调用时,走到mono的函数如下:
graph TD
A[mono_lookup_pinvoke_call] --> B[cached_module_]
B --> C[cached_module_load]
C --> D[mono_dl_open]
D -->E[LoadLibrary]
本质上就是调用Windows的LoadLibrary加载dll,然后调用GetProcAddress(函数名)获取对应函数的地址。理论上讲使用FreeLibrary(hmodule)可以把dll释放掉。为了验证想法,单独作了下小测试:
// 新建一个MathDll工程,并生成dll,代码如下:
extern "C"
{
__declspec(dllexport) int DoAdd(int a, int b)
{
return a + b;
}
}
// 再新建一个DllLoadUnload win32 console工程,代码如下:
#include
#include
extern "C"
{
typedef int (func)(int, int);
}
int main()
{
while (1)
{
HMODULE hmodule = ::LoadLibrary("MathDll.dll");
func* add = (func*)::GetProcAddress(hmodule, "DoAdd");
std::cout << "add result = " << (*add)(1, 2) << std::endl;
::FreeLibrary(hmodule);
system("pause");
}
return 0;
}
// 代码结束
在system("pause")时,先不要结束程序,会发现MathDll.dll可以删除。
把FreeLibrary注释掉,再编译一次,会发现在system("pause")时,删除MathDll.dll会提示dll被占用。
因此,验证通过,可以使用FreeLibrary来释放引用住的dll。
所以,可以mono加个接口,释放指定名字的dll,然后在Unity中加个接口来调用就可以,完。