2016-03-09 83 views
0

我在使用P/Invoke從C#代碼中使用C++函數時遇到問題。我使用http://www.codeproject.com/Articles/403285/P-Invoke-Tutorial-Basics-Part上的教程作爲基本的例子,一旦我得到了它的工作,我適應了我自己的代碼。使用P/Invoke會導致系統AccessViolationException

這是產生一個System.AccessViolationException,並附加信息:'試圖讀取或寫入受保護的內存。這往往表明其他內存已經損壞。「

我的C++頭文件 'NativeLib.h' 如下:

#include <string> 

#ifndef _NATIVELIB_H_ 
#define _NATIVELIB_H_ 

#ifndef MYAPI 
#define MYAPI 
#endif 

#ifdef __cplusplus 
extern "C" { 
#endif 

    MYAPI float modelScore(std::string word); 

#ifdef __cplusplus 
} 
#endif 

#endif // _NATIVELIB_H_ 

其中MYAPI是 'MYAPI = __ declspec(dllexport)的' 定義爲預處理器定義。 .cpp文件,「NativeLib.cpp」如下:

#include "NativeLib.h" 
#include <stdio.h> 
#include "lm/model.hh" 
#include <iostream> 
#include <string> 

MYAPI float modelScore(std::string word) { 
    using namespace lm::ngram; 
    Model model(---MODEL FILE LOCATION---); 

    State state(model.BeginSentenceState()), out_state; 
    const Vocabulary &vocab = model.GetVocabulary(); 

    return model.Score(state, vocab.Index(word), out_state); 

} 

我從C#中使用下面的代碼訪問此:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace PInvokeTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      modelScore("a"); 
      Console.WriteLine("Press enter to close..."); 
      Console.ReadLine(); 
     } 

     [DllImport("NativeLib.dll", CallingConvention = CallingConvention.Cdecl)] 
     private static extern float modelScore(string word); 
    } 
} 

的代碼沒有建立與所有適當的庫失敗鏈接幷包含在標題路徑中。 C++代碼很適合C++本身,所以我的問題在於將代碼與C#鏈接起來,但我看不出問題在哪裏。任何幫助將非常感激。

回答

1

P/Invoke默認情況下將C#string編組成C字符串。你的C函數的參數應該是const char*,而不是std::string

通常,您應該避免導出帶有取決於非POD類型的簽名的函數,如std::string。消費者(在這種情況下,C#)不知道DLL所使用的std::string的內存佈局,所以它甚至不能創建一個來調用你的函數。

+0

謝謝,那已經解決了! – Rahul

相關問題