我正在从C#受管函数调用一个非托管且非常简单的C ++函数(位于JNIDiskInfoDll.dll
中),如下所示:
C ++:
#include "stdafx.h"
#include "AtaSmart.h"
#include <iostream>
#include <string.h>
extern "C" __declspec(dllexport) char* __cdecl getSerial(LPTSTR inCStrIn)
{
return "abcdefg";
}
C#:
using System;
using System.Runtime.InteropServices;
namespace HardInfoRetriever
{
class DiskInfoRetreiver
{
[DllImport("C:\\Users\\User1\\Documents\\Visual Studio 2017\\Projects\\HardInfoRetriever\\Debug\\JNIDiskInfoDll.dll",
EntryPoint = "getSerial", CallingConvention = CallingConvention.Cdecl,
BestFitMapping = false, ThrowOnUnmappableChar = true, CharSet = CharSet.Ansi)]
public static extern String getSerial([MarshalAs(UnmanagedType.LPTStr)]String _driveletter_);
public static String getSerialNumber(String driveletter)
{
try
{
return getSerial(driveletter);
}
catch (Exception e)
{
throw e;
}
}
}
}
我的问题是,运行应用程序后,我得到两个连续的错误,分别为projectName.exe has triggered a breakpoint
和Unhandled exception at 0x77110E23 (ntdll.dll) in projectName.exe: 0xC0000374: A heap has been corrupted (parameters: 0x7712E930).
。知道尽管我遇到了这些错误,但该函数仍在返回所需的输出。
请注意,getSerial
C函数具有LPTSTR inCStrIn
参数,因为我在删除仍然存在错误的整个代码(仅保留return "abcdefg";
)之前就已经使用了它。>
我不知道这里可能是什么问题。我试图将Charset
中的DllImport
更改为Unidcode
,但是仍然遇到相同的错误。有什么帮助吗?
答案 0 :(得分:0)
感谢@PaulMcKnezie的评论:
不返回指针。确保此功能正常运行的肯定方法是 调用方提供缓冲区,该函数将字符串复制到 缓冲区。
因此,我使用了与提到的here相同的方法相同的概念
使用BSTR *参数返回字符串。
最后,下面是我的代码的最终工作版本:
C ++:
extern "C" __declspec(dllexport) HRESULT __cdecl getSerial(LPTSTR inCStrIn, BSTR* inCStrOut)
{
*inCStrOut= SysAllocString(L"abcdefg");
return S_OK;
}
C#:
using System;
using System.Runtime.InteropServices;
namespace HardInfoRetriever
{
class DiskInfoRetreiver
{
[DllImport("C:\\Users\\User1\\Documents\\Visual Studio 2017\\Projects\\HardInfoRetriever\\Debug\\JNIDiskInfoDll.dll",
EntryPoint = "getSerial", CallingConvention = CallingConvention.Cdecl,
BestFitMapping = false, ThrowOnUnmappableChar = true, CharSet = CharSet.Ansi)]
//[return: MarshalAs(UnmanagedType.LPTStr)]
public static extern int getSerial([MarshalAs(UnmanagedType.LPTStr)] string _driveletter_, [MarshalAs(UnmanagedType.BStr)] out string serial);
public static String getSerialNumber(string letter)
{
try
{
string serial;
int result = getSerial(letter, out serial);
if (result == 0)
{
return serial;
}
return null;
}
catch (Exception e)
{
throw e;
}
}
}
}