使用PInvoke对ssdeep的fuzzy.dll(不平衡堆栈)造成麻烦

时间:2012-08-07 08:58:40

标签: vb.net interop pinvoke

我正在尝试在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函数'(Blah):: fuzzy_hash_filename'的调用使堆栈失衡。这很可能是因为托管PInvoke签名与非托管目标签名不匹配。检查PInvoke签名的调用约定和参数是否与目标非托管签名匹配。

(FWIW如果我忽略警告,那么呼叫似乎成功,所以我必须靠近)

为了实现这一目标,我需要对我的定义做出哪些改变?

2 个答案:

答案 0 :(得分:3)

我在MSDN forums找到了有同样问题的人:

  
      
  1. 关于PInvokeStackImbalance。
  2.         

    1.1这通常是由于API使用的调用约定与C#代码中为API声明的调用约定不匹配。

         

    1.2默认情况下,如果未设置DllImportAttribute的CallingConvention参数,则默认使用StdCall。

         

    1.3如果DoSomething()API要使用__cdecl(这是C ++项目中的默认值),那么您应该使用以下声明:   C#代码中的DoSomething():[DllImport(@“dll.dll”,   CallingConvention = CallingConvention.Cdecl)]

         

    1.4另外,我建议您将API声明为extern“C”,否则它将受到C ++编译器的名称损坏。

答案 1 :(得分: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