0

次のように、管理されていない非常に単純な 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;
            }
        }
    }
}

私の問題は、アプリケーションを実行した後、 と という 2 つの連続したエラーが発生することprojectName.exe has triggered a breakpointですUnhandled exception at 0x77110E23 (ntdll.dll) in projectName.exe: 0xC0000374: A heap has been corrupted (parameters: 0x7712E930).。これらのエラーが発生していますが、関数はまだ目的の出力を返していることを知っています。

エラーが続くコード全体を削除する前にC関数を使用していたため、 getSerialC関数にはパラメーターがあることに注意してください(のみ保持)。LPTSTR inCStrInreturn "abcdefg";

ここで何が問題になるのかわかりません。を に変更しようとしCharsetましたDllImportUnidcode、それでも同じエラーが発生します。何か助けてください。

4

1 に答える 1

0

@PaulMcKnezie のコメントに感謝します:

ポインターを返さないでください。これを機能させる確実な方法は、呼び出し元がバッファーを提供し、関数が文字列をバッファーにコピーすることです。

だから私はここで言及されているのと同じ方法と同じ概念を使用しました。

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;
            }
        }
    }
}
于 2019-05-22T10:30:50.217 に答える