トップ回答者
C++で作ったdllをC#で使う

質問
-
dll側(straylight.dll):
#pragma once
# define API __declspec(dllexport)
#else
# define API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C"{
#endif
API const char* str();
#ifdef __cplusplus
}
#endifAPI const char* str()
{
const char* a="000";return a;
}C#側:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;using System.Runtime.InteropServices;
namespace test
{public partial class MainForm : Form
{
[DllImport("straylight.dll", EntryPoint = "str", CallingConvention = CallingConvention.Cdecl)]
public static extern string str();public MainForm()
{
InitializeComponent();string a;
a = str(); //----①ブレークポイント付きif (a == null) //---②ブレークポイント付き
{
MessageBox.Show("1");
}
else
{
MessageBox.Show("0");
}
}
}
}C#側に付いているブレークポイントは、①番を進んでから、②番に行けないでデバック終了しました。
出力元のメッセージは、「マネージ (v4.0.30319)' はコード -2147483645 (0x80000003) で終了しました。」
どの原因でしょうか?教えてください。
回答
-
補足です。
相互運用マーシャラーによるメモリ管理に次のように説明があります。ランタイムは常に CoTaskMemFree メソッドを使用してメモリを解放します。操作の対象であるメモリが CoTaskMemAlloc メソッドで割り当てられていない場合は、IntPtr を使用し、適切なメソッドを使って手動でメモリを解放する必要があります。同様に、メモリを解放するべきではない場合に、自動的なメモリの解放を回避することもできます。たとえば、Kernel32.dll から、カーネル メモリへのポインターを返す GetCommandLine 関数を使用するような場合です。手動によるメモリの解放の詳細については、「Buffers のサンプル」を参照してください。
でBuffersのサンプルには
ネイティブ GetCommandLine 関数は、オペレーティング システムが割り当てて所有する、バッファーへのポインターを返します。 戻り値の型として文字列をマーシャリングする場合、相互運用マーシャラーは、関数から返された元の LPTSTR 型が指すメモリを解放する必要があると見なします。 このメモリがマーシャラーによって自動的にクリアされるのを回避するために、マネージ GetCommandLine プロトタイプは文字列の代わりに IntPtr 型を返します。 PtrToStringAuto メソッドはアンマネージ LPSTR 型をマネージ文字列オブジェクトにコピーし、必要に応じて文字形式を拡張します。
と書かれています。
すべての返信
-
補足です。
相互運用マーシャラーによるメモリ管理に次のように説明があります。ランタイムは常に CoTaskMemFree メソッドを使用してメモリを解放します。操作の対象であるメモリが CoTaskMemAlloc メソッドで割り当てられていない場合は、IntPtr を使用し、適切なメソッドを使って手動でメモリを解放する必要があります。同様に、メモリを解放するべきではない場合に、自動的なメモリの解放を回避することもできます。たとえば、Kernel32.dll から、カーネル メモリへのポインターを返す GetCommandLine 関数を使用するような場合です。手動によるメモリの解放の詳細については、「Buffers のサンプル」を参照してください。
でBuffersのサンプルには
ネイティブ GetCommandLine 関数は、オペレーティング システムが割り当てて所有する、バッファーへのポインターを返します。 戻り値の型として文字列をマーシャリングする場合、相互運用マーシャラーは、関数から返された元の LPTSTR 型が指すメモリを解放する必要があると見なします。 このメモリがマーシャラーによって自動的にクリアされるのを回避するために、マネージ GetCommandLine プロトタイプは文字列の代わりに IntPtr 型を返します。 PtrToStringAuto メソッドはアンマネージ LPSTR 型をマネージ文字列オブジェクトにコピーし、必要に応じて文字形式を拡張します。
と書かれています。