2012年4月24日 星期二

在C#中如何使用C/C++所編譯出來的dll?

最近因為有同學問到如何在C#中使用C/C++所事先產生出來的dll問題,在這邊也大概總結一下自己在嘗試這個問題所找到的資料,避免之後某一天需要用到又要重新google (關鍵字: marshal, DllImport)

結合多語言(如 Visual C++ 與 Visual C#)以便利軟體開發是.NET framework的重點核心之一。
廢話不多說,先來看如何在Visual C++中使用自己所產生出來的Dll[1]。
有了這個基本概念後,就可以知道要在Visual C++中創造一個dll,在該function/method的header file中要加上__declspec(dllexport),已確保該function/method可以被export到Dll中。
而對應的.cpp檔就只是單純的實做對應method的內容。

如[2]所說,微軟只提供C-function的marshal對應的方法(也就是以function-based的marshal,並沒有class level的marshal)。
所以如果要marshal一個C-functions的Dll還蠻容易的,可以參考[3] (注意,如果使用visual studio系列,把.so換成.dll就可以了)。

如果更複雜一些,需要marshal C++ class的Dll話(unmanaged Dll),可以參考[2]。
主要的做法就是利用C-functions的做法為該Class做封裝(Wrap),例如說可以提供function-based的方式存取以開發/設計好的class。(不過要Wrap的話有點複雜就是了 :( )

此外,如果要用C-function的marshal,需要額外注意C與C++之間的call convention的差異[4]。


底下列出小弟測試好的程式碼:

1. 定義已編好的C-functions DLL


---------- c_MathFuncsDll.h----------


#ifndef c_MathFuncsDll_H
#define c_MathFuncsDll_H

#include stdio.h;
extern "C"{

    // Returns a + b
  __declspec(dllexport) double Add(double a, double b);

  // Returns a - b
  __declspec(dllexport) double Subtract(double a, double b);

  // Returns a * b
  __declspec(dllexport) double Multiply(double a, double b);

  // Returns a / b
  __declspec(dllexport) double Divide(double a, double b);
    }
#endif

---------- c_MathFuncsDll.cpp----------

#include "c_MathFuncsDll.h"



double Add(double a, double b)
{
    return a + b;
}

double Subtract(double a, double b)
{
    return a - b;
}

double Multiply(double a, double b)
{
    return a * b;
}

double Divide(double a, double b)
{
    if (b == 0)
    {
        return -1;
    }

    return a / b;
}


1. 定義要呼叫C-functions Dll的C#檔(xxx/c_MathFuncsDll.dll為欲使用的library檔案)


using System;
using System.Runtime.InteropServices;

namespace Csharp_MyMathFuncs
{
    class Program
    {
        [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Add")]
        static extern double Add(double a, double b);
        [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Subtract")]
        static extern double Subtract(double a, double b);
        [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Multiply")]
        static extern double Multiply(double a, double b);
        [DllImport("xxx/c_MathFuncsDll.dll", EntryPoint = "Divide")]
        static extern double Divide(double a, double b);

        static void Main(string[] args)
        {
            double d1 = 5.0d;
            double d2 = 20.0d;
            Console.Write(Add(d1,d2));
        }
    }
}



參考連結:
[1] Walkthrough: Creating and Using a Dynamic Link Library
[2] How to Marshal a C++ Class
[3] PInvoke ( How to Call C from C# )
[4] LIst of Calling Conventions and Mangling Names in C++

2011年12月3日 星期六

求知若飢 < 沒有飯吃

這一陣子真的是現實壓力太大了,,,主要都是來自於$$$$$$$
想想, 學生時代還真輕鬆阿,,,努力做研究,讀paper,,之外什麼都可以不用煩惱.
自從弄丟了車子之後,,整個人都改變了...變成了一個以金錢為主的人生...

不過最近真的有種感覺了,,,,很明顯的感覺自己再混, 很明顯的感覺自己沒有在進步!
因為薪水領的一樣多, 所以就拒絕多做一些額外的事情. 久而久之就變成老油條...
但是兩年後發現,,,自己在這一段時間裡面都沒有任何的成長....其實多做一些事情可以多長一些知識, 雖然內心上是拒絕的(因為多做多累, 薪水又沒有比較多), 但現在反而有種莫名的遺憾.

以知識層面來說, 我想要讀很多paper, 想要知道更多高手的想法.
每次覺得就算是top conference的那些paper, 也很少有令人為之一嘆的想法, 多數的想法不稀奇, 只是多了很複雜的數學模型去包裝. 但是我對那些paper都嗤之以鼻,,,但是只要讀到好的paper, 就會讚賞不已!
另外一方面, 覺得自己的想法很創新,,,reviewer的結果也沒有什麼不好( 但結果總是在接受與拒絕邊緣)...但總是討不到chair的歡喜....

在這樣的怨念底下, 又在加上被塞一堆額外的鳥事,,,自然就會加重討厭的成分......

即便是如此,,,,我還是想要進步. 但是首先要克服對周遭人事物的不爽!


2011年3月20日 星期日

cuda under matlab mex

最近需要用到cuda來提升方法的速度,,,因為用得環境是matlab, 所以就透過mex來連結cuda與matlab.
事實上, matlab 2010b以經可以直接在matlab底下撰寫gpu的kernel function了(參考), 所以如果您有capability >= 1.3 以上的顯示卡, 就不需要透過mex file來當做matlab與cuda的溝通橋樑了.
如果您需要mex的話, 請參考底下.

環境: win7 + cuda 3.1 + matlab 2010b.
先從底下這個網址下載好心人寫好的setup_cuda_mex.m, 接著在matlab底下直接run 該.m檔.
注意:
 1. win 7在C槽底下有permission的限制, 所以要將產生的cuda_mex.pl放到matlab/bin底下
 2. x64的問題該聯結底下有好心人回答.

正常來說這樣應該就可以順利產生.mexw64檔案了.

FAQ1. cuda底下並不支援double-precison的加速效果, 可以參考這篇文章.
如果真的有double-precision的需求, 可在 setup_cuda_mex.m中 'compflags' 底下加上
' --arch sm_13' 就有支援double.
FAQ2. launched timeout問題:
如果在測試的過程中有出現"launched timeout"等訊息的話, 可以參考這篇文章,
如果不是register 或share memory用得過多的話, 就是kernel func花了太多時間在執行上.
所以有個方法可以設定kernel func的launched time參考.(不是很建議, 因為該時間內您的螢幕將會沒有反應XD)
cmd->regedit-> enter
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ GraphicsDrivers
TdrLevel = yourtimeoutinsec
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ GraphicsDrivers \ DCI\
Timeout = yourtimeoutinsec

然後reboot your computer, then it is done.

2011年3月9日 星期三

cuda inside visual studio

之前一些實驗需要用到cuda, 所以就大概紀錄一下安裝cuda在visual studio上的文章.
env: win 7 + visual studio 08
cuda version: cuda 3.2

steps:

1. 安裝cuda toolkit
%%假設64bits安裝在C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2
2. 安裝cuda sdk 32bits or 64bits
%%假設64bits安裝在C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2

3. 設定visual studio
Tools->Options ->CV++ Directories:
Executable file:
C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2\shared\bin\win64\Release
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2\bin
include file:
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v3.2\include
C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2\shared\inc
C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2\C\common\inc 
lib file:
C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2\shared\lib 
C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2\C\common\lib
C:\Program Files (x86)\NVIDIA GPU Computing Toolkit\CUDA\v3.2\lib\x64

4. 安裝npp(NVIDIA Performance Primitives library, optional)
%%假設64bitx安裝在C:\NVIDIA\NPP_SDK_0_9_3_1_X64
32bits or 64bits

Tools->Options ->CV++ Directories:
include file:
C:\NVIDIA\NPP_SDK_0_9_3_1_X64\common\npp\include
C:\NVIDIA\NPP_SDK_0_9_3_1_X64\common\FreeImage\include
lib file:
C:\NVIDIA\NPP_SDK_0_9_3_1_X64\common\lib
C:\NVIDIA\NPP_SDK_0_9_3_1_X64\common\FreeImage\lib


5. 編譯example code
%%C:\ProgramData\NVIDIA Corporation\NVIDIA GPU Computing SDK 3.2\C\src
開啟其中一個example, 重編譯, 沒問題的話就是ok了.
note: 若要編譯x32的code, 路徑設定成win32底下即可(或是直接安裝32bits的版本也可).

2010年12月6日 星期一

forward/inverse search in latex

當您正利用latex撰寫長篇幅的文章時, Forward and Inverse search 是一個很方便的功能.
底下就利用texmaker 與 sumatra pdfreader 記錄一下如何達到forward/inverse search

texmaker:
option->Configure->Commands->pdflatex:
pdflatex -synctex=-1 -interaction=nonstopmode %.tex


pdfviewer:
"C:\Program Files (x86)\SumatraPDF\SumatraPDF_tex.exe" -reuse-instance -inverse-search """"C:\Program Files (x86)\TexMakerX\texmakerx.exe""" """%%f""" -line %%l" %.pdf


C:\Program Files (x86)\SumatraPDF\SumatraPDF_tex.exe: 為您的sumatra path
C:\Program Files (x86)\TexMakerX\texmakerx.exe: 則是editor的位置

Forward search
User->User Commands-> Edit User Commands:
Menu item: Forward search
command:
dde://SUMATRA/control/[ForwardSearch("?am.pdf","?am.tex",@,0,0,1)]

設定完成之後, 即可作forward search
(選定tex檔案上的某一行, alt+shift+f1 即可跳至pdf上的對應行數)

Inverse search
sumatra.pdf -> setting -> options -> set inverse search command-line:
"C:\Program Files (x86)\TexMakerX\texmakerx.exe" "%f" -line %l
設定完成之後, 即可inverse search
(double-click pdf 上的行, 即可跳至對應的tex檔案上)

reference:
[TexMakerX]: Forward & Inverse Search
LaTeX: TexmakerX with SumatraPDF

2010年10月23日 星期六

給自己的信

在youtube上面有一首還蠻紅的歌曲,,,叫做"手紙: 敬啟者 給十五歲的你"

聽阿聽,,,好像該寫點信給未來的自己...

如果這個真的事寫給自己3年後看的信的話,,,我要寫什麼內容呢?

整理一下再寫

2010年10月12日 星期二

該感謝的是...

從呱呱落地的那一刻開始,,,到現在大概已經過了二十有六個年頭了,,,,
今天突然又翻開了自己以前過去寫的文章(in bbs),,,過去往事如剛發生一般的記憶猶新. 想想自己是該寫一些心得或是感想當作記錄,,,以免bbs掛掉而把過去的記憶也順便忘掉! (這篇文章會不定時的更新)
事件一: 從一進大學那一刻開始, 系上學長姐為我們這屆舉行了系學會的選舉, 主要想選出一些比較熱心的同學來服務大家...正當選舉結束後, 雙方候選人有人高興的恭賀A同學當選, 也有人安慰B同學的說下次再多努力. 當然也有一些核心人物(C同學)被雙方給糾纏住,,,搞得雙方不是人...
而這個的同時, 好管閒事的我在班版上po上一篇: "當你當選的同時,,是不是也讓班上的分裂情況更加的嚴重."
在如此白目的同時,,,一個同學在我版上密文的寫出: "當你自以為事的描述這件事情的時候, 有沒有考慮過ABC這三個同學的感受?" 第一次受到這個衝擊,,讓我察覺到原來我所謂的描述這件事情對別人來說真的是很白目的事情. 或者是說,,,我選擇了一條三派系的人都不接受的路...
當然在這之後難免會有因為這件事情所造成的風波,,,不過我還是很感謝這位同學當時肯挺身在我犯錯的時候給了我一巴掌. 而在往後的大學生活裡, 也跟了這位同學學習了很多.

事件二: 大學暑假的時候有一陣子很想多賺點外快,,,而那時候剛好有小小工作室在應徵coding intern, 主要是利用php, js寫一些web app的案子. 而那一陣子有投了一家履歷, 對方也有打電話來做個簡單的phone interview. interview結果後對方問我哪時候可以上班,,但是由於地點在台北, 所以我跟對方回應說先找看看有沒有住的地方在跟對方說. 之後, 也因為這件事情稍微跟家人吵了一架(家人的觀點是說打工不用去到台北這麼遠的地方, 但是我的觀點是說這種工作在鄉下找不到). 因為住的地方的問題, 問了住台北的朋友能不能住他家的事情,,但是之後才發現事情不是這麼簡單. 那時候我考慮的點只有: 早上八點上班, 晚上五點下班, 只要有的地方能睡覺即可~ 但是我同學說生活這件事情不是這麼簡單, 如果在台北我迷路了, 他也沒時間可以來幫我(他也有他自己的事情要忙); 另一點是要暫住他家一陣子, 可能無形中對他家人造成不方便(因為他家人作息比較不一樣); 最重要的是, 萬一發生了事情, 對方不就要承擔這個責任?(因為雙方家長認知不同)
在這件事情之前, 我一直認為只要我想做的事, 沒什麼事情是不可能的,,,但是現實中存在的因素總是會讓你覺得障礙很難跨過. 不過現在想起來還是覺得自己那時候真的衝了點,,很多細節沒有仔細想過以及規劃過!!萬一出了事情也很難對爸媽有個交代!! 很感謝那位台北同學跟我說了這麼多東西,,,雖然當下不能接受, 但是還是很感謝你願意花這麼多時間指出我的錯誤. 而在往後的大學生活裡, 也因為這個同學而多采多姿.