我正在尝试为.Net程序集创建NuGet程序包,它会对原生的win32 dll进行pinvoke.我需要将程序集和本机dll打包,并将程序集添加到项目引用中(此部分没有问题),并且应将本机dll复制到项目输出目录或其他相关目录中.
我的问题是:
在Visual Studio 2010中,VC++ Directories > Executable Directories我已指定了路径glew32d.dll.但是,当我运行可执行文件时,它仍然会抱怨.
另一方面,如果我将DLL复制到本地文件夹然后运行可执行文件,它不会抱怨.
有人可以告诉我如何解决这个问题吗?另外,为什么Visual Studio无法识别该路径?
更新 场景:我目前使用的模板项目用作许多项目的入门代码.此模板取决于glew32d.dll.我通常将所有相关的dll存储在一个公共bin文件夹中.我希望引用这个文件夹,Visual Studio可以从那里读取dll,而不是每次都要复制dll.处理这个问题的好方法是什么?
有关如何在运行时设置搜索目录的SO有一个很好的答案DllImport.使用两行代码可以正常工作.
但是,许多开源项目改为使用LoadLibrary函数.有传言称通过委托调用本机方法的速度较慢.我把它们称为"谣言",因为我只在两个地方看过这个,这无论如何都是微优化.
最有趣的地方是这篇博文:http://ybeernet.blogspot.com/2011/03/techniques-of-calling-unmanaged-code.html
在那里,作者测量了不同技术的表现:
NNanomsg使用功能的代表,但提到的博客文章与评论"的这比传统的P中的性能的影响/ Invoke的,显然不是好"在这条线.
来自MSFT的ASP vNext的Kestrel服务器使用与Libuv库相同的技术:这是代码
我认为代理使用比简单的DllImport更麻烦,并且考虑到性能差异,我想知道为什么面向性能的库使用委托代替设置dll搜索文件夹?
是否有任何技术原因,如安全性,灵活性或其他 - 或者这仅仅是品味问题?我不明白其理由 - 作者是否可能没有足够的搜索StackOverflow!?
我有一个用C++编写的DLL,它导出一个函数CreateRisk.该函数返回一个接口指针,如下所示:
extern "C"
{
__declspec(dllexport) IRisk* __stdcall CreateRisk()
{
return new Risk();
}
}
Run Code Online (Sandbox Code Playgroud)
IRisk派生自IUnknown并具有自定义方法Calculate:
class IRisk: public IUnknown
{
public:
virtual int __stdcall Calculate(int i,double s) = 0;
};
Run Code Online (Sandbox Code Playgroud)
Risk类实现了IRisk接口(这里省略了实现).
我想要的是在c#中调用CreateRisk函数并获取对IRisk的引用.
我在c#中定义了一个包装器接口
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IRisk
{
[PreserveSig]
int Calculate(int i,double s);
}
Run Code Online (Sandbox Code Playgroud)
我在C#中添加了一个dll条目
[DllImport("Risk.dll")]
extern static IntPtr CreateRisk();
Run Code Online (Sandbox Code Playgroud)
我可以在C#中调用CreateRisk并获取IntPtr的值类型.有没有办法将IntPtr编组到c#IRisk接口,以便我可以在C#中调用Calculate方法?
我曾尝试过Marshal.GetIUnknownForObjectInContext,Marshal.GetObjectForIUnknown,但无济于事.
我知道创建COM组件可以做到这一点.但是,COM组件需要在系统中注册.我想避免这些麻烦,让C#直接使用C++ dll导出的接口.
PS:
以下是我的Risk类实现:
class IRisk : public IUnknown
{
public:
virtual int __stdcall Calculate(int i,double y ) = 0;
};
class Risk:public IRisk
{
int count;
public: …Run Code Online (Sandbox Code Playgroud) 可能的重复:
在 .NET 中指定 DllImport 的搜索路径
我有一个非托管的 DLL。为了清除,它是我想在我的 c# 代码中使用的 C++ dll。问题是它是一个 Windows 应用程序,用户可以将它安装在他们选择的任何目录中。所以我不能用静态路径引用它,也找不到给出相对路径的方法。这是我试过的代码:
[DllImport("mydll.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
public void SetDllDirectory(string lpPathName)
{
try
{
bool r = SetDllDirectory(lpPathName);
}
catch (Exception ex)
{
throw ex;
}
}
public void SetDirectoryPath()
{
try
{
DirectoryInfo directory = new DirectoryInfo(System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath));
if (directory.Exists)
SetDllDirectory(directory.ToString() + "\\mydll.dll");
}
catch (Exception ex)
{
throw ex;
}
}
Run Code Online (Sandbox Code Playgroud)
下面是我收到的错误。
无法在 DLL“mydll.dll”中找到名为“SetDllDirectory”的入口点。
这个问题可能是复制品
我需要将SglW32.dll导入我的解决方案.
但我得到:
AccessViolation exeption:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.
我不能只使用DllImport.在那种情况下,找不到dll.
这是完整的例子.
using System;
using System.Runtime.InteropServices;
namespace TestDllimport
{
class Program
{
static void Main(string[] args)
{
var a = new MyClass();
var result = a.getValue();
}
}
class FunctionLoader
{
[DllImport("Kernel32.dll")]
private static extern IntPtr LoadLibrary(string path);
[DllImport("Kernel32.dll")]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
public static Delegate LoadFunction<T>(string dllPath, string functionName)
{
var hModule = LoadLibrary(dllPath);
var functionAddress = GetProcAddress(hModule, functionName);
return Marshal.GetDelegateForFunctionPointer(functionAddress, typeof(T));
}
}
public class MyClass
{
//Define your path …Run Code Online (Sandbox Code Playgroud) 我今天问了这个问题,但它被错误地关闭了,我无法选择重新打开它。因此,我不得不再问一遍。
我有一个类,其中有一长串定义,如下所示:
[DllImport(NativeLibraryName, EntryPoint = "FunctionName", CallingConvention = CallingConvention.Cdecl)]
public static extern void FunctionName();
Run Code Online (Sandbox Code Playgroud)
参数“NativeLibraryName”由编译器开关设置。但是,我想在运行时设置此参数。我的问题是,我需要考虑两种不同的 DLL:一种用于 32 位系统,一种用于 64 位系统,并且它们的名称不同。我想要实现的是确定应用程序是否以 64 位或 32 位运行并使用正确的 DLL。我需要加载正确的 DLL,否则我会遇到 BadImageFormatExceptions。
切换为代表
我可以使用 Reflection 生成一个文件,其功能与使用像这样的委托给出的文件相同。在这里,我可以在运行时提供正确的 DLL 的路径。
重命名 DLL
我还可以重命名这两个 DLL,使它们具有相同的名称,但将它们放在不同的目录中。然后我可以选择要从中加载 DLL 的文件夹。
这两个选项都可以正常工作,但我正在处理的项目是现有项目的一个分支,我希望尽可能少地进行更改,以便我可以轻松地将原始项目的更新合并到我的项目中。
我很高兴你的任何想法。
该线程被错误地建议作为我的问题的解决方案,并且原始线程在那之后被关闭。该线程讨论了类似的问题,但它没有提供适用于我的问题的解决方案。事实上,实际上提出了我自己想出的解决方案之一,但我正在寻找更好的方法来做到这一点。
c# ×5
dll ×3
.net ×2
c++ ×2
pinvoke ×2
dllimport ×1
interop ×1
loadlibrary ×1
nuget ×1
nuget-spec ×1
unmanaged ×1
visual-c++ ×1
windows ×1