麻烦

2012-08-07 127 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