使用P / Invoke从C#代码中使用C ++函数时遇到问题。我已经使用http://www.codeproject.com/Articles/403285/P-Invoke-Tutorial-Basics-Part上的教程作为基本示例,一旦我开始工作,我就根据自己的代码进行了调整。
这产生了一个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#联系起来,但我看不出问题出在哪里。任何帮助都会非常感激。
答案 0 :(得分:1)
默认情况下,P / Invoke将您的C#string
编组为C字符串。您的C函数的参数应为const char*
,而不是std::string
。
通常,您应该避免导出具有依赖于非POD类型的签名的函数,例如std::string
。消费者(在这种情况下,C#)不知道你的DLL使用的std::string
的内存布局,所以它甚至无法创建一个用来调用你的函数。