2016-03-09 51 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

相关问题