C#を使う最大のメリットって、やっぱり、Visual Studioですよね!」って自信を持って言いたいですね。

という心境ではあるんですが、私の仕事はどっちかというとC++よりなので、どうしても、DllImportはお友達という側面があります。そうすると、プログラム実行時に、

AnyCPUなアセンブリ.exe
ネイティブC++.dll

みたいな感じになって、要は、AnyCPUなアセンブリがネイティブC++ちゃんを呼び出す構図になるんですが、この構成、64-bitの環境で開発をしていたりすると相当なジレンマを抱えることになります。

普通に実行する場合には、x64環境なので、「ネイティブC++.dll」さんは、64-bit版を配置しておくべきなんですが、VS上からデバッグしようとすると、win32(32-bit版)を置いておかないと行けなかったり、あるいは、「ネイティブC++.dll」さんのデバッグ版は激遅なので、デバッグ中でも普通はリリース版を置いておきたかったりと、様々な面倒なシチュエーションに出くわすことになります。

で、これを解決する方法を考えたよという話です。
簡単に言うと、

AnyCPUなアセンブリ.exe
win32/
ネイティブC++.dll
x64/
ネイティブC++.dll

というディレクトリ構成にしてしまえという。「AnyCPUなアセンブリ.exe」は、賢いので、自分が実行されている環境に応じて、どっちをロードするか見てくれるという。

で、どうするかというと、次みたいなコードをアプリに取り込んでしまえという。
これは、MainWindow.xaml.csとかの例ですが、もっと早い段階がよければ、そこでやっても良いですね:

static MainWindow()
{
SetDllDirectory("");
#if DEBUG
if (setDllLocation(true))
return;
#endif
setDllLocation(false);
} /// <summary>
/// Controlling DLL directory which native DLLs are loaded from.
/// </summary>
/// <param name="debug">Whether this is debug mode or not.</param>
/// <returns><c>true</c> if DLL directory is correctly set; otherwise <c>false</c>.</returns>
static bool setDllLocation(bool debug)
{
var appDir = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
if (debug) appDir = Path.Combine(appDir, "debug");
var dllDir = Path.Combine(appDir, IntPtr.Size == 8 ? "x64" : "win32");
if (Directory.Exists(dllDir))
{
Debug.WriteLine(string.Format("Set DLL Location ({0}): {1}", debug ? "Debug" : "Release", dllDir));
SetDllDirectory(dllDir);
return true;
}
return false;
} [DllImport("Kernel32.dll")]
static extern bool SetDllDirectory(string lpPathName);

やってることの内容としては、 SetDllDirectory APIを呼び出して、DLLをロードするディレクトリを事前に変更しておこうと。
C++だと、delayloadがらみを調整して同じような事が出来ますが、C#でのDllImportは完全に実行時にバインディングを解決することになるので、かなりこういう芸当がやりやすいです。

で、上のコードにはオマケがあって、デバッグ版では、さらに、

AnyCPUなアセンブリ.exe
debug/
win32/
ネイティブC++.dll
x64/
ネイティブC++.dll

みたいなレイアウトにしておけば、デバッグ版のDLLを見つけてロードしてくれると。
いずれにしても、デバッグ時にDLLをコピーしたり移動したりの右往左往がかなり軽減されるという意味では開発が楽になると思います。

C#からネイティブDLLを呼び出す場合のVSからのデバッグのジレンマを解決する的更多相关文章

  1. [SharePoint 2010]Sandboxed Solution (沙箱解決方案)

    現有的SharePoint 2007系統中,我們如果要安裝客製化的程式碼到系統中,我們必須製作一個解決方案包裝檔(Solution Package),然後在系統的中央管理後台中,真對整個伺服器農場Fa ...

  2. 假如现在有一堆长度大于3小于9的电话号码,用座机呼叫,如果出现这样的号码【123和12345】那么12345将永远不会被拨出,因为拨到123的时候电话已经呼出了,试写一个函数输出所有不能被呼出的电话号码(java实现)

    解题: 假如现在有一堆长度大于3小于9的电话号码,用座机呼叫,如果出现这样的号码[123和12345]那么12345将永远不会被拨出,因为拨到123的时候电话已经呼出了,试写一个函数输出所有不能被呼出 ...

  3. 技术解析:锁屏绕过,三星Galaxy系列手机也能“被”呼出电话

    近期,由两位安全研究人员,Roberto Paleari及Aristide Fattori,发布了关于三星Galaxy手机设备安全漏洞的技术细节.据称,Galaxy手机可在锁屏状态下被未授权的第三方人 ...

  4. asterisk中使用dahdi通道呼出的注意事项

    asterisk中使用dahdi通道呼出的注意事项 在使用dahdi通道呼出的时候,可以在Dial中对呼出所使用的通道进行指定选择.以下面的例子来说明: 场景说明:数字板卡单E1,使用pri信令,1- ...

  5. iOS中如何呼出另一个应用

    我们经常会遇到在一个应用里面呼出另一个应用的需求,比如在文档里面点击地址,调用safari来打开网页:比如在文件浏览器里面点击某种文件,自动激活一个应用来打开文件. iOS里面对于这样的需求使用URL ...

  6. 在动态链接库dll中弹出对话框

    在动态链接库dll中弹出对话框步骤: 1.添加Dialog资源,然后在资源视图的对话框界面右击添加类,输入类名MyDlg,使得其继承与CDialogEx.(继承CDialog应该也可以)2.在新生成的 ...

  7. gentoo emacs 中文输入法 呼出

    最近在另外一台电脑上面安装 gentoo和 emacs,但是碰到奇怪的问题,在旧电脑上面,可以使用 ctrl + space 呼出输入法,而新电脑只能触发 复制功能. 经过在网上查找和两台电脑之间的对 ...

  8. 安卓手机H5底部fix定位,呼出键盘底部会上浮解决办法

    <script type="text/javascript">var windowInnerHeight = window.innerHeight; //获取当前浏览器 ...

  9. vos设置可呼出手机或固话

    问题: 默认公司只让呼出手机号码,但有的客户要求能打固话,怎么办? 落地网关——补充设置——落地前缀——落地被叫改写规则 在改写规则里添加固话号段即可 具体案例: 5201——1表示让520号段只能拨 ...

随机推荐

  1. codeforces 1077F2. Pictures with Kittens (hard version)单调队列+dp

    被队友催着上(xun)分(lian),div3挑战一场蓝,大号给基佬紫了,结果从D开始他开始疯狂教我做人??表演如何AKdiv3???? 比赛场上:A 2 分钟,B题蜜汁乱计数,结果想得绕进去了20多 ...

  2. tensorflow 语音识别报错

    cuDnn由7.1版本改为7.4.2.24版本,成功

  3. postgresql语句

    查询oracle数据库所有表数据量 select t.table_name,t.num_rows from user_tables t ORDER BY t.num_rows desc 查询postg ...

  4. Python list和 np.Array 的转换关系

    一.List转String 1.str list转 string a_list = ["h","e","l","l",& ...

  5. VUE-Windows系统下搭建vue环境

    一.安装node.js(https://nodejs.org/en/) 下载完毕后,可以安装node,建议不要安装在系统盘(如C:).注意记下路径..   此处默认安装这4项即可,点击Next按钮. ...

  6. Linux下 tftp 服务器的安装与使用

    安装步骤: 1. 安装xinetd, tftp-hpa tftpd-hpa a.  sudo apt-get install xinetd b.  sudo apt-get install tftp- ...

  7. JGUI源码:鼠标中键滚动再次优化(5)

    //电脑端中键滚动事件 var mousewheel = getBrowserInfo() == "Firefox" ? "DOMMouseScroll" : ...

  8. [物理学与PDEs]第1章第8节 静电场和静磁场 8.1 静电场

    1. 静电场: 由静止电荷产生的稳定电场. 2. 此时, Maxwell 方程组为 $$\bex \Div{\bf D}=\rho_f,\quad \rot{\bf E}={\bf 0}. \eex$ ...

  9. burp Suite 模块Authz 使用方法

    这个模块是朋友告诉我的,然后进行了研究使用方法. 以下为个人理解,如有错误感谢各位纠正. 0x00 安装Authz Extender > BApp Store > Authz > i ...

  10. Contest2154 - 2019-2-28 高一noip基础知识点 测试1 题解版

    传送门 预计得分:100+100+100+100=400 实际得分:55+100+60+80=295 细节决定成败啊!!! T1 这道题思路很简单,就是一些细节很变态坑人 首先,数据不一定是有序的,虽 ...