C#でアンマネージドの関数を呼ぶ時のLPBYTEの処理

このQ&Aのポイント
  • C#におけるアンマネージド関数でLPBYTEを扱う方法について困っています。
  • VC++で使っていた関数をC#から呼び出したいが、LPBYTEの処理で問題が発生しています。
  • C#でLPBYTEと同様の領域を扱う方法がわからず、エラーが発生しています。
回答を見る
  • ベストアンサー

C#でアンマネージドの関数を呼ぶ時のLPBYTEの処理

C#に首を突っ込み始めたばかりの初心者です。 VC++で使っていた関数をC#から使いたいのですが、四苦八苦しています。 引数としてLPBYTEをとるような関数ですが、C#からどのようにして呼べばいいのか困っています。呼ぶには呼ぶようですが、たぶんLPBYTEの処理がうまくいっていないので、例外処理されてしまいます。 ソースはこんな感じです。(途中、省略しています。) unsafe public class foo : ... { [DllImport("bar.dll")] private static extern int hoge(StringBuilder pBuf, int i); unsafe private void button(...) { StringBuilder pBuf = new StringBuilder(256*256); try { hoge(pBuf, 100); } catch{ ... } } } hogeの最初の引数が、LPBYTEだったところで、StringBuilderならいけるかなぁ、と思ってやってみたのですが、どうもダメっぽいです。おもいっきりcatchに入っていきます。 そもそも、C#でLPBYTEのような領域の扱いがわかっていないのがいけないのかもしれません... 素人の質問ですみません。

  • pokuda
  • お礼率51% (158/305)

質問者が選んだベストアンサー

  • ベストアンサー
  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

LPSTR(または、char*)は、Stringでいけます

関連するQ&A

  • CからC++の関数呼び出し

    CからC++の関数を呼び出して値を取得したいのですが、コンパイルエラーになってしまいます。 呼び出す関数内でさらに同じクラスの関数を呼び出して値をreturnしたいだけなのですが、 ご教示願います。 ソースは下記のような感じです。 Cソース(AAA.c) main(){ ・・・・・ if ( funcA() ){ ・・・・ } } C++ソース(BBB.cpp) int clsB::funcB { return iflg; } extern "C" { int funcA() { return funcB(); } } ※上記externは特に何かの関数内に書いているわけではありません。 C++ヘッダ(BBB.hpp) class clsB : public XXX { private: int iflg; ・・・・ public: int funcB(); ・・・・ } 上記にコンパイルすると、 externしている箇所でfuncBはスコープにありません?のようなエラーが出てしまいます。 ラッパ関数を使って使用するなどと聞いたのですが、やり方がいまいちわかりません。 どうか教えていただけますでしょうか。 また、他にやり方があるかと思いますが、いいやり方があれば教えていただけると幸いです。 以上です、よろしくお願いいたします。 不足内容あれば指定願います。

  • VS2010C#からのDLL使用について

    VS2010 C#からVC6で作成したDLLへint配列を引数として渡したい。 VC++6で作成されたDLLがあります。 ここで定義されている int test(char*fname,int* x,int* y); ファイルのフルパスを渡すと 返り値が関数の成否のコードを返す。 処理内で x,y にファイルから読み込んだ値が それぞれ上限100個としてセットして返す といったような関数を C#から呼び出したいのですが 1 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref int* x,ref int* y); 2 [DllImport("dll名", EntryPoint = "test", CallingConvention = CallingConvention.Cdecl)] public unsafe static extern int test(IntPtr fname, ref IntPtr x,ref IntPtr y); と2種類の呼び出し方法をこころみました。 ファイルのフルパスは IntPtr fnamePtr = Marshal.StringToHGlobalAnsi(string型ファイルフルパス); としております。 1の場合は int[] resX = new int[100]; int[] resY = new int[100]; fixed(int* x= resX) fixed(int* x= resY) として呼び出そうとすると : エラー CS1657: '固定変数' であるため、'x' を ref または out 引数として渡せません となり失敗してしまいます。 2 で試みた場合 int size = sizeof(int)*100; IntPtr x = Marshal.AllocHGlobal(size); IntPtr y = Marshal.AllocHGlobal(size); と引き渡したところ ビルドは通りますが 実行時に System.AccessViolationException' のハンドルされていない例外が 発生しました。 追加情報: 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。他のメモリが壊れていることが考えられます。 となってしまいます。 どのようにすれば思惑通りの結果を得られますでしょうか。

  • C#からC++のDLLを使いたい時

    C#からC++(unmanaged)のDLLを使いたい時、 DLLをどのように参照すればよいのでしょうか。 [DllImport("名前.dll")] extern static double 関数名(); という指定は分かるのですが、 それだけじゃもちろん、 「DLL (名前.dll) を読み込めません。」 ってなりますよね・・・。

  • C言語でのconstを返す関数

    お世話になります。 C言語では、const の関数というのを認めているようですが、どうも使い方が分かりません。 const int foo() {  これは通常のint foo()とどのように違うのでしょうか。  よろしくお願いいたします。

  • C#から、C++作成dll内の関数を呼び出す方法

    C#から、C++で作成したdll内の関数を呼び出す方法は、以下の方法で実現できました。(メッセージボックスで "10" が表示されました) [C++側のヘッダファイル] #ifdef CPPDLL_EXPORTS #define CPPDLL_API __declspec(dllexport) #else #define CPPDLL_API __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ CPPDLL_API int fnCppDll(); #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ [C++側のソースファイル] CPPDLL_API int fnCppDll() { return 10; } [C#側] using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApp1 { public partial class Form1 : Form { [DllImport("CppDll.dll")] public static extern int fnCppDll(); public Form1() { InitializeComponent(); } private void buttonGo_Click(object sender, EventArgs e) { int n = fnCppDll(); MessageBox.Show(n.ToString()); } } } 今回お聞きしたいのは、int型ではなく、C++側で型を定義されたクラスのオブジェクト(の参照)を返す関数を、C#側から呼び出し、それをどうやってC#で受け取るかを教えていただきたいのです。 具体的には以下のように実装してみました。 [C++側のヘッダファイル] #ifdef CPPDLL_EXPORTS #define CPPDLL_API __declspec(dllexport) #else #define CPPDLL_API __declspec(dllimport) #endif class CPPDLL_API CCppDll { public: int data; CCppDll(void); }; #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ CPPDLL_API CCppDll& fnCppDll(); // C#が参照渡しということで、参照を返すようにした。 #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ [C++側のソースファイル] CPPDLL_API CCppDll& fnCppDll() { CCppDll* a = new CCppDll(); return *a; } CCppDll::CCppDll() : data(11) // メンバーは 11 で初期化 { } [C#側] using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApp1 { // ビルドエラーが起きるないように、とりあえず、C++と同じ(ような)クラスを定義 public class CCppDll { public int data; } public partial class Form1 : Form { [DllImport("CppDll.dll")] public static extern CCppDll fnCppDll(); public Form1() { InitializeComponent(); } private void buttonGo_Click(object sender, EventArgs e) { int n; CCppDll cls = fnCppDll(); // ※ n = cls.data; MessageBox.Show(n.ToString()); } private void buttonCancel_Click(object sender, EventArgs e) { Close(); } } } 実装しながらも、「これじゃあ、ダメだろうな。いかにもダメだな」と思った通り、上の※の部分で以下の例外が発生しました。 ------- 例外(ここから) ------- マネージド デバッグ アシスタント 'FatalExecutionEngineError' : 'ランタイムの重大なエラーが発生しました。エラーのアドレスは 0xcc9ff5a2、スレッド 0x36c8 です。エラー コードは 0xc0000005 です。これは CLR のバグであるか、またはユーザー コードのアンセーフまたは確認不可能な部分にバグがある可能性があります。このバグの一般的な原因には、スタックが壊れる可能性のある COM-interop または PInvoke のユーザー マーシャリング エラーが含まれています。' ------- 例外(ここまで) ------- 明らかに基本的なことが分かっていないことから起因するエラーと思われますが、具体的にどう実装すれば、正常に動きますか。(メッセージボックスで "11" を表示) よろしくお願いします。

  • templateクラスについて

    先ほど以下のようなプログラムを書いたのですがコンパイルを通すことができません。 //適当なポインタを保持するだけのクラス template <class _type> class hoge { private:   //適当に変数を保持   _type val; public:   //コンストラクタで適当に値をセット   hoge() : val( 0 ){}   //このクラスから唯一ポインタを引っ張ってくる方法   friend _type getVal( const hoge& foo )   {     // そのまま返す     return foo.val;   } }; void func( const hoge<int>& foo ) {   //値を引き出す   getVal( foo ); } void main() {   //実体化   hoge<int> foo;   //値を引き出す   getVal( foo );   //関数の先で値を引き出す   func( foo ); } 上記のようなプログラムを書いたのですが、main関数内でgetValを呼び出す場合はとくに問題ないのですがfunc関数を呼び出してfunc関数内でgetValを呼び出すと error C3861: 'getVal': 識別子が見つかりませんでした error C2365: 'getVal' : 再定義; 以前の定義は '以前は不明な識別子' でした。 コンパイルされたクラスの テンプレート のインスタンス化 'hoge<_type>' の参照を確認してください というエラーが出てしまいます。 func関数の引数を( const hoge<int>& foo )からvoid func( hoge<int> foo )のように参照渡しから実体渡しに変更するとコンパイルが通り、実行もできるのですが、なぜこれでコンパイルが通るのか理由がいまいちよくわかりません。 またやはり、コンストラクタ、デストラクタの問題などから実体渡しより、参照渡しを使いたいのですがどのようにプログラムを書けば今回の問題を解決できますでしょうか。 よろしくおねがいします。 /* VisualStudio2005 AcademicEdition MicroSoft WindowsXP Professional 32bit */

  • C#でのWNetAddConnection3の使い方を教えてください

    現在、C#(VisualStudio2005)で共有フォルダの認証を行い、 そのフォルダ内のファイルを読み込む処理を行ないたいと考えています。 ■動作------------------------------------------------------ 1.ボタン押下によってフォルダ(\\aaa)をユーザ(user)、パスワード(pass)で認証を行なう 2.ファイル(bbb.txt)の内容をメッセージボックスに出力する 3.認証を切る ■現在の実装状況-------------------------------------------- private void btnGetShareFileData_Click(object sender, EventArgs e) { NETRESOURCE netresource = new NETRESOURCE(); netresource.dwType = 1; netresource.lpLocalName = null; netresource.lpRemoteName = "\\\\aaa"; netresource.lpProvider = null; try { int returnNo1 = WNetAddConnection3(IntPtr.Zero, ref netresource, "user", "pass", 0); System.IO.StreamReader streamReader = new System.IO.StreamReader("\\\\aaa\\bbb.txt", System.Text.Encoding.GetEncoding(932)); MessageBox.Show(streamReader.ReadToEnd()); int returnNo2 = WNetCancelConnection2("\\\\aaa", "0", true); } catch (Exception ex) { MessageBox.Show(ex.Message); } } [StructLayout(LayoutKind.Sequential)] public struct NETRESOURCE { public int dwType; public string lpLocalName; public string lpRemoteName; public string lpProvider; } [DllImport("mpr.dll")] private static extern int WNetAddConnection3( System.IntPtr hWndOwner, ref NETRESOURCE lpNetResource, string lpPassword, string lpUserName, int dwFlags ); [DllImport("mpr.dll")] private static extern int WNetCancelConnection2( string lpName, string dwFlags, bool fForce ); [DllImport("mpr.dll")] private static extern int WNetAddConnection2( ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, int dwFlags ); ■結果------------------------------------------------------ WNetAddConnection3の戻り値が「487」で System.IO.StreamReader streamReaderを実行されると 「ログオン失敗:ユーザ名を認識できないかまたはパスワードが間違っています。」 とエラーになってします。 WNetAddConnection3でのログオン自体がうまくできていないのでしょうですが、 どうすればよいのかがわかりません。 (ちなみにWNetAddConnection2でやってみても同様です) どなたか教えていただけないでしょうか? いろいろなページは参考にさせていただいているのですが、 知識が足らず読み解くことができないので、 できればサンプルコード等を教えていただけると助かります。 よろしくお願いいたします。

  • クラスのメンバ変数のnew

    こんにちは。 クラスのメンバ変数の動的割り当てで困っていることがあります。 コンストラクタ内でメンバ変数に動的割り当てをするんですが、そこで例外処理をしなければならないようです。 例 class foo::foo() { try{ hoge = new int[100]; // hogeの代入処理 // } catch { delete[] hoge; hoge = NULL; } } foo::~foo() { delete[] hoge; hoge = NULL; } しかしこれだと不十分なようで、なかしかの対策をしないとメモリリークが起きてしまいそうなんですが どのようにやるんでしょうか?

  • ユーザー定義関数との日本語のやりとり(C#)

    unsafe void test(int *x,int *y) { *x=15; *y=16; } unsafe private void button1_Click(object sender, EventArgs e) { int a,b; test(&a,&b); label1.Text =a+b; } 上のような感じにユーザー定義関数と変数のやりとりをさせているのですが、 日本語のやりとりの方法がよく分かりません。 unsafe void test { } 内で "テスト" を変数に入れ、 それを unsafe private void button1_Click{ } 内の変数に代入したいです。 記述例を教えて下さい。

  • C# 他のアプリケーションから複数行取得

    C#で外部のアプリケーションのリッチテキストコントロールの複数行の文字列を取得したいです。 自分は下のコードを書いたのですが、これだと1行しか取得できませんでした。 どこが悪いでしょうか。 ここでは対象のアプリケーションをA、リッチテキストのコントロールをRichEditとします。 button1をクリックしたら、textbox1にRichEditの内容が表示されるようなものを作ろうとしています。 //ここから [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, StringBuilder lParam); private const int WM_GETTEXT = 0x000D; private void button1_Click(object sender, EventArgs e) { IntPtr hWnd = FindWindow("A", ""); if (hWnd != null) { IntPtr hWndChild = FindWindowEx(hWnd, IntPtr.Zero, "RichEdit", ""); StringBuilder strBuilder = new StringBuilder(); SendMessage(hWndChild, WM_GETTEXT, strBuilder.Capacity, strBuilder); StringReader strReader = new StringReader(strBuilder.ToString()); string stResult = string.Empty; while (strReader.Peek() >= 0) { string stBuffer = strReader.ReadLine(); stResult += stBuffer + System.Environment.NewLine; } strReader.Close(); textbox1.Text = stResult; } }

専門家に質問してみよう