首页 文章

使用P / Invoke导致系统AccessViolationException [重复]

提问于
浏览
0

这个问题在这里已有答案:

我在使用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#联系起来,但我看不出问题出在哪里 . 任何帮助将非常感激 .

1 回答

  • 1

    默认情况下,P / Invoke将C# string 编组为C字符串 . 你的C函数的参数应该是 const char* ,而不是 std::string .

    通常,应避免导出具有依赖于非POD类型的签名的函数,例如 std::string . 消费者(在这种情况下,C#)不知道你的DLL使用的 std::string 的内存布局,所以它甚至无法创建一个调用你的函数 .

相关问题