将 LPTSTR 参数传递给 DLL 会在项目中C++出现访问冲突

Passing LPTSTR Parameter to DLL gives Access Violation in C++ project

本文关键字:C++ 访问冲突 项目 参数传递 LPTSTR DLL      更新时间:2023-10-16

我正在调用一个未记录的DLL中的函数,该函数解压缩了一个文件。

标头的声明/分配方式一定有错误,但无法弄清楚出了什么问题。

VS 2010中的项目字符集是Unicode。

可以使用下面的代码片段从 C# 成功调用 DLL 函数(但我需要让它在 c++ 中工作(:

[DllImport("unpacker.dll", EntryPoint = "UnpackFile", PreserveSig = false)]
internal static extern IntPtr UnpackFile(byte[] file, int fileSize,
[MarshalAs(UnmanagedType.LPWStr)] StringBuilder header, int headerSize);

如果我取消移动一个标题的评论,则会弹出"访问冲突"。该函数还返回 0,这在 C# 中没有。

有什么想法吗?

VC++ 2010 项目中的代码:

// unpacker.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h> 
#include <fstream>
using namespace std;
typedef void* (*UnpackFile)(unsigned char*, int, LPTSTR, int);
int _tmain(int argc, _TCHAR* argv[])
{
    LPTSTR header; 
    //Move this and get a access violation on the _UnpackFile(filetounpack... line
    static unsigned char *filetounpack; //Buffer to byte array with the file to unpack
    int filelen; //variable to store the length of the file
    HINSTANCE dllHandle; // Handle to DLL
    UnpackFile _UnpackFile; // Function pointer
    ifstream filetoread; //Stream class to read from files
    static LPTSTR header2;  //Buffer for the header 2nd

    filetoread.open ("c:/projects/testfile.bin", ios::in | ios::binary|ios::ate); 
    filelen = filetoread.tellg(); //read the length
    filetounpack = new unsigned char [filelen]; //allocate space
    filetoread.seekg (0, ios::beg); //set beginning
    filetoread.read ((char *)filetounpack, filelen); //read the file into the buffer
    filetoread.close(); //close the file
    dllHandle  = LoadLibrary(_T("unpacker.dll"));
    _UnpackFile = (UnpackFile)GetProcAddress(dllHandle, "UnpackFile");
    //header = new _TCHAR[filelen]; //Allocate memory for header
    header2 = new _TCHAR[filelen]; //Allocate memory for header
    //Access violation reading location 0xffffffffffffffff!!!
    void* tmp = _UnpackFile(filetounpack ,filelen ,header2 ,filelen); 
    delete[] filetounpack;
    delete[] header;
    delete[] header2;
    FreeLibrary(dllHandle); 
    return 0;
}
 typedef void* (*UnpackFile)(unsigned char*, int, LPTSTR, int);

这与 C# 声明的调用约定属性不匹配。 C# 的默认值为 StdCall,本机C++项目的默认值为 __cdecl。 修复:

 typedef void* (__stdcall * UnpackFile)(unsigned char*, int, LPTSTR, int);

请记住,错误检查在C++中从来都不是可选的,您确实需要检查 LoadLibrary(( 和 GetProcAddress(( 是否成功。 在 C# 中自动,而不是在C++中自动。 这两个函数在失败时都返回 NULL。