通过DllImport调用非托管函数时损坏的堆
本文关键字:损坏 函数 DllImport 调用 通过 | 更新日期: 2023-09-27 18:16:43
我正在使用一个从c#应用程序用C/c++编写的非托管dll。我有兴趣从dll中使用以下函数:
static void StorePath(const std::string& path, wchar_t *out_path,
int *out_path_length){
wcslcpy(out_path, c_str_w(path), *out_path_length);
*out_path_length = path.size();
}
int WINAPI BrowseForDirectory(
int allow_portable, int allow_online,
wchar_t *t_directory, int *e_directory_length,
wchar_t *m_directory, int *m_directory_length){
.
.
. //initializing new forms and checking product keys
StorePath(form->SelectedEDirectory().TopDir(), e_directory,
e_directory_length);
StorePath(form->SelectedMDirectory(), m_directory,
m_directory_length);
}
头文件:
#if defined(_WIN32) && !BUILD_WITHOUT_DLLS &&!defined(ECLIPSE_CBUILDER_WORKAROUNDS)
# if BUILDING_EXPORT_LIBRARY
# define EXPORT_DLL __declspec(dllexport)
# else
# define EXPORT_DLL __declspec(dllimport)
# endif
#else
# define EXPORT_DLL
#endif
extern "C" {
int WINAPI BrowseForDirectory(
int allow_portable, int allow_online,
wchar_t *t_directory, int *e_directory_length,
wchar_t *m_directory, int *m_directory_length)
}
然后,我尝试在我自己管理的c#类库中调用这个函数,方法如下:
[DllImport("MyDLL.dll", CharSet = CharSet.Ansi)]
public static extern int BrowseForDirectory(Int32 allowOnline,
Int32 allowPortable,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder eDirectory,
ref Int32 eDirLength,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder mDirectory,
ref Int32 mDirLength);
最后,我试图在c#应用程序中使用它,通过调用它:
var eDir = new StringBuilder(260);
var mDir = new StringBuilder(260);
var eDirLength = eDir.Length;
var mDirLength = mDir.Length;
try
{
var result = Viewer.BrowseForDirectory(1, 1, eDir,
ref eDirLength, mDir, ref mDirLength);
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
然而,我得到一个堆损坏,但现在我的应用程序退出,因为status_stack_buffer_overflow——关于嵌入的断点。更改c++代码不是一种选择。我有合适的参考文献和程序集。
我做错了什么?
我看到的问题是你的字符集不匹配。非托管代码返回UTF-16格式的文本,但是您的p/invoke指定ANSI编码的文本。将p/调用更改为:
[DllImport("MyDLL.dll", CharSet = CharSet.Unicode)]
public static extern int BrowseForDirectory(
int allowOnline,
int allowPortable,
StringBuilder eDirectory,
ref int eDirLength,
StringBuilder mDirectory,
ref int mDirLength
);
我假设c_str_w()
接受8位编码字符串,并返回指向wchar_t
的null终止数组的指针。