「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 Beta Round #51 D. Beautiful numbers(数位dp)

    题目链接:https://codeforces.com/contest/55/problem/D 题目大意:给你一段区间[l,r],要求这段区间中可以整除自己每一位(除0意外)上的数字的整数个数,例如 ...

  2. NowCoder -- 牛客小白月赛10

    A--勘测 推下公式  a[i] = a[i-1] + a[i-2] +2 #include<stdio.h> #include<string.h> ]; int main() ...

  3. kubernetes云平台管理实战: 自动加载到负载均衡(七)

    一.如何实现外界能访问 外界访问不了 1.启动svc [root@k8s-master ~]# cat myweb-svc.yaml apiVersion: v1 kind: Service meta ...

  4. java集合分割

    java集合分割成等份的小集合: private <T> List<List<T>> getSubList(List list,int len) { if(list ...

  5. oldboy s21day13装饰器和推导式

    #!/usr/bin/env python# -*- coding:utf-8 -*- # 2.请为 func 函数编写一个装饰器,添加上装饰器后可以实现:执行func时,先输入"befor ...

  6. spring boot打包

    1.application继承SpringBootServletInitializer  重写configure方法如下图 2.去掉项目中多余的main方法 3.将pom.xml打包改为war包 4. ...

  7. [物理学与PDEs]第2章第1节 理想流体力学方程组 1.3 理想流体力学方程组的数学结构

    1.  局部音速 $c$: $c^2=\cfrac{\p p}{\p \rho}>0$. 2.  将理想流体力学方程组 $$\beex \bea \rho\cfrac{\p {\bf u}}{\ ...

  8. Notepad++崩溃后文件内容找不到问题

    也许是因为Ctrl + s 摁太多太频繁,一不小心Notepad++崩溃了 重启后发现原来的文件还在,但是文件内容全部都被清空了 我没有手动备份这个文件, 如何找回??? 点击设置,首选项,里面有个备 ...

  9. lucene学习的小结

    pom.xml设置 <dependency> <groupId>junit</groupId> <artifactId>junit</artifa ...

  10. 2018-2019-1 20189208《Linux内核原理与分析》第九周作业

    活动 main函数编译有问题,div 函数和系统中某个函数重名,浮点输出有问题,scanf也有问题 修改如下 scanf_s("%d %d", &a, &b); p ...