c# - 使用 P/Invoke 导致系统 AccessViolationException

标签 c# c++ pinvoke access-violation

<分区>

我在使用 P/Invoke 从 C# 代码使用 C++ 函数时遇到问题。我使用了 http://www.codeproject.com/Articles/403285/P-Invoke-Tutorial-Basics-Part 上的教程作为一个基本示例,一旦我让它工作,我就将它改编为我自己的代码。

这会产生一个 System.AccessViolationException,并带有附加信息:'试图读取或写入 protected 内存。这通常表明其他内存已损坏。”

我的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);
    }
}

代码正在构建而不会失败,所有适当的库都已链接并包含在 header 路径中。 C++ 代码从 C++ 本身运行良好,所以我的问题在于将代码与 C# 链接,但我看不出问题出在哪里。非常感谢任何帮助。

最佳答案

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

一般来说,您应该避免导出带有依赖于非 POD 类型的签名的函数,例如 std::string。使用者(在本例中为 C#)不知道您的 DLL 使用的 std::string 的内存布局,因此它甚至无法创建一个来调用您的函数。

关于c# - 使用 P/Invoke 导致系统 AccessViolationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35902939/

相关文章:

c# - P/Invoke、Pinning 和 KeepAlive 最佳实践

c# - 了解 Windows Phone 开发中的数据绑定(bind)

c# - ReactiveUI 与 ICollectionView

c++ - C++如何写日志文件以便用记事本实时读取

c++ - 什么是 C++ 中的 instanceof 的等价物?

c# - 如何编码双指针?

c# - 正则表达式 选择 [A-Z ] 除了两个连续空格

c# - 在 C# 中设置模块化程序的最佳方式

c++ - 对类型的非常量左值引用 - 使用 Class 类型的参数时 Objective-C++ 包装器中的错误

c# - 使用 PInvoke 的 CryptoAPI 的 SignerTimeStampEx2