从 DllImport 启动的 C++ 方法的访问冲突

Posted

技术标签:

【中文标题】从 DllImport 启动的 C++ 方法的访问冲突【英文标题】:Access violation on c++ methods launched from DllImport 【发布时间】:2015-05-14 18:39:04 【问题描述】:

我对一些从 DllImport 启动的方法有奇怪的问题。

在原生 c++ 中我有代码:

#define BUFSIZE 4096

int _tmain(int argc, _TCHAR* argv[])

    wchar_t *tekst = L"D:\\matiz\\Dokumenty\\!FIRMA TRIM-POT\\Firmowe";
    PrintTekst(tekst);


bool PrintTekst(wchar_t *tekst)
   
    DWORD  retval = 0;
    BOOL   success;
    TCHAR  buffer[BUFSIZE] = TEXT("");
    TCHAR  buf[BUFSIZE];
    TCHAR** lppPart =  NULL ;
    retval = GetFullPathNameW(tekst, BUFSIZE, buffer, lppPart);
    return true;


bool __stdcall PrintTekstExtern(wchar_t *tekst)

    return PrintTekst(tekst);

当我直接从主函数调用 PrintTekst 方法时,一切正常,但是当我使用 DllImport 调用此方法时,在线:

TCHAR  buffer[BUFSIZE] = TEXT("");

我有访问冲突异常。这是很奇怪的情况,因为实际上我没有使用任何参数,在这种情况下来自管理器代码。

方法,在c#中启动:

[DllImport("Pointers.exe", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Auto)]
public static extern bool PrintTekstExtern(string tekst);

static void Main(string[] args)

    string cos = @"D:\matiz\Dokumenty\visual studio 2013\Projects\Pointers\PointersSharp\bin\Debug";
    var status = PrintTekstExtern(cos);

你能帮帮我吗?

【问题讨论】:

你为什么不把它做成一个DLL而不是exe? 请看这个链接它可能对你有帮助social.msdn.microsoft.com/Forums/vstudio/en-US/… 【参考方案1】:

最大的问题是您试图从可执行文件而不是 DLL 导入函数。这是首先要解决的问题,也是导致致命崩溃的真正原因。

除此之外,非托管函数是:

bool __stdcall PrintTekstExtern(wchar_t *tekst)

您的 p/invoke 是:

[DllImport("...", CallingConvention = CallingConvention.StdCall, 
    CharSet = CharSet.Auto)]
public static extern bool PrintTekstExtern(string tekst);

这里有一个小问题。返回值被编组为 4 字节布尔类型,但非托管代码使用 1 字节类型。在这里阅读:http://blogs.msdn.com/b/jaredpar/archive/2008/10/14/pinvoke-and-bool-or-should-i-say-bool.aspx

通过改变 p/invoke 来解决这个问题:

[DllImport("...", CallingConvention = CallingConvention.StdCall, 
    CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool PrintTekstExtern(string tekst);

我还建议使用 CharSet.Unicode,因为非托管代码使用 wchar_t,因此明确使用 16 位文本。

【讨论】:

他们还需要在字符串上指定封送处理,并使用extern "C"从DLL中导出它,所以它不是名称损坏 @Mgetz 字符串很好。我怀疑使用了 .def 文件,因此该函数未修饰地导出。 这可能是,根据我的经验,P/Invoke 最不可能失败并且最喜欢表现出色的是那种让编组器几乎没有猜测的地方 @Mgetz 这里没有猜测。 CharSet.Auto 很清楚,尽管正如我所说,我更喜欢 CharSet.Unicode

以上是关于从 DllImport 启动的 C++ 方法的访问冲突的主要内容,如果未能解决你的问题,请参考以下文章

从 C++ 调用 C DLL 会导致访问冲突,但 C# 项目与 DllImport 工作

有啥方法可以调试从 C# DllImport 调用的 c++ dll?

如何使用 DLLImport 将字符串从 C# 传递到 C++(以及从 C++ 到 C#)?

Dllimport 将字符串从 C# 传递到 C++

调用从 c# 返回 char* 的 c++ dll 函数。无法使用 DllImport()

使用 Dllimport 将一个非常大的字符串作为字节数组从 C++ 传递到 C#