I am calling an un-managed and very simple C++ function (located in JNIDiskInfoDll.dll
) from a C# managed one as follows:
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;
}
}
}
}
My problem is that after running the application I get two successive errors saying projectName.exe has triggered a breakpoint
and Unhandled exception at 0x77110E23 (ntdll.dll) in projectName.exe: 0xC0000374: A heap has been corrupted (parameters: 0x7712E930).
. Knowing that although I'm getting these errors, the function is still returning the desired output.
Please note that the getSerial
C function has the LPTSTR inCStrIn
parameter since I was using it before I did remove the whole code (keeping only return "abcdefg";
) where the error persists.
I don't know what could be the problem here. I tried to change the Charset
in the DllImport
into Unidcode
, but still getting same errors. Any help please?
Thanks to the comment of @PaulMcKnezie saying:
Don't return pointers. The sure way to get this to work is for the caller to provide the buffer, and the function copies the string to the buffer.
So I used the same concept as the same method mentioned here that is about
Returning a String With a BSTR * Parameter.
Finally, below is the final working version of my code:
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;
}
}
}
}
User contributions licensed under CC BY-SA 3.0