麻煩

2012-08-07 126 views
1

我試圖調用一個方法上ssdeep fuzzy.dll麻煩

.h文件是here和友好的參考是here

具體來說,我試圖調用此方法....

int fuzzy_hash_filename (
     const char * filename, 
     char * result 
) 

我有以下...

<DllImport("C:\SSDeep\Fuzzy.dll", EntryPoint:="fuzzy_hash_filename")> 
Private Shared Function fuzzy_hash_filename(
              <InAttribute(), 
              MarshalAsAttribute(UnmanagedType.LPStr)> 
              ByVal Filename As String, ByVal Result As StringBuilder) As Integer 
End Function 


Public Shared Function FuzzyHash(Filename As String) As String 
    Dim Ret As New StringBuilder 
    Ret.Capacity = NativeConstants.FUZZY_MAX_RESULT 
    Dim Success = fuzzy_hash_filename(Filename, Ret) 
    If Success <> 0 Then 
     Throw New Exception("SSDeep fuzzy hashing failed") 
    End If 
    Return Ret.ToString 
End Function 

如果我運行此代碼,VS給了我多種形式對話

一個調用的PInvoke函數「(胡說):: fuzzy_hash_filename」有不平衡的堆棧。這很可能是因爲託管的PInvoke簽名與非託管目標籤名不匹配。檢查PInvoke簽名的調用約定和參數是否與目標非託管簽名相匹配。

(FWIW呼叫似乎成功,如果我忽略了警告,所以我必須接近)

做我需要做我的定義中,以這種打算什麼變化?

+0

也許這將幫助:http://social.msdn.microsoft.com/Forums/en -US/csharplanguage/thread/e03c925e-c094-40f1-9fb0-20ac8dc5972d/ – ken2k 2012-08-07 09:13:12

回答

3

我發現有人對MSDN forums同樣的問題:

  1. 關於PInvokeStackImbalance。

1.1這通常是由於API使用的調用約定與C#代碼中爲API聲明的調用約定不匹配造成的。

1.2默認情況下,如果未設置DllImportAttribute的CallingConvention參數,則默認使用StdCall。如果DoSomething()API要使用__cdecl(這是C++項目中的默認設置),那麼您應該在C#代碼中使用以下聲明: DoSomething():[DllImport(@「dll.dll 「, CallingConvention = CallingConvention.Cdecl)]

1.4另外,我建議你聲明API爲e​​xtern」C「,否則它將受到C++編譯器的名稱修改。

+0

謝謝ken,你在那裏爲我節省了很多時間 – Basic 2012-08-07 09:21:36

1

接受的答案似乎已經解決了原始提問者的問題,但在c#中的等效代碼不適用於我。在嘗試了越來越複雜的註釋之後,迴歸基礎知識最終確實奏效了。爲了大家的參考,我包含了三種接口函數和工作代碼的聲明(針對ssdeep version 2.9構建)。

//Note: StringBuilder here is the standard way to do it, but is a perf hit because unicode stringbuilder can't be pinned when martialling char*. 
    //See http://msdn.microsoft.com/en-us/magazine/cc164193.aspx#S4 

    //int fuzzy_hash_buf(const unsigned char *buf, uint32_t buf_len, char *result) 
    [DllImport("fuzzy.dll")] 
    public static extern int fuzzy_hash_buf(StringBuilder buf, int buf_len, StringBuilder result); 

    //int fuzzy_hash_filename(const char* filename, char* result) 
    [DllImport("fuzzy.dll")] 
    static extern int fuzzy_hash_filename(string filename, StringBuilder result); 

    //int fuzzy_compare (const char *sig1, const char *sig2) 
    [DllImport("fuzzy.dll")] 
    static extern int fuzzy_compare(string sig1, string sig2); 

    static void Main(string[] args) 
    { 
     StringBuilder buf = new StringBuilder("test"); 
     StringBuilder result0 = new StringBuilder(150); 
     fuzzy_hash_buf(buf, 4, result0); 
     Console.WriteLine(result0); 

     string filename = "test.txt"; 
     StringBuilder result1 = new StringBuilder(150); 
     fuzzy_hash_filename(filename, result1); 
     Console.WriteLine(result1); 

     int matchScore = fuzzy_compare(result0.ToString(), result1.ToString()); 
     Console.WriteLine("MatchScore: " + matchScore); 
    } 

輸出:

ssdeeptest。EXE 3:Hn的:Hn的 24:gRnIM7stweRp + fEWU1XRk +/M98D6Dv3JrEeEnD/MGQbnEWqv3JW:gRIMwtrMU1Bk2I3Jrg53JW MatchScore:0

+0

感謝你發佈了一個備用方法。 FWIW我使用[P/Invoke interop assistant](http://clrinterop.codeplex.com/releases/view/14120)從ssdeep頭文件生成存根等。它爲我節省了大量的工作,並且很可能已經抽象了導致你走得更長的問題。 – Basic 2012-08-31 16:30:25