1

私は Classic C++ で PInvoke を使用するのが初めてで、昨日この質問をしました: Using Windows API functions in .NET

次のように、非常に単純な C++ プログラムを作成しました。

#include <iostream>
#include <stdio.h>
#include <string>
extern "C" __declspec(dllexport) int hello()
{
  //printf ("Hello World!\n");
  return 1;
} 

次に、次のコマンドを使用して DLL をコンパイルしました: g++ -c mydll.cpp 次に、次のコマンドを使用して共有ライブラリを作成しました: g++ -shared -o mydll.dll mydll.o、次に mydll.dll を C:\Windows\syswow64 にコピーしました。 .

次に、新しい VB.NET プロジェクトを作成し、次のコードを作成しました。

    Imports System.Runtime.InteropServices
Public Class TestPlatformInvoke
    <DllImport("mydll.dll", CallingConvention:=CallingConvention.Cdecl)> _
    Public Shared Function hello() As Integer
    End Function
    Public Sub New()
        Try
            Dim test As Integer = hello() 'Line 6 ex As Exception
            'I don't swallow exceptions
            MsgBox("test")
        Catch ex As Exception

        End Try
    End Sub
End Class

hello() を呼び出した後、アプリケーションは終了します。例外はスローしません。

私はこれがどのように機能するかを理解しようとしています。私は C++ の商業的な経験がありません。大学での学歴のみ。

これは、mydll.dll の Dependancy Walker のイメージです。

ここに画像の説明を入力

4

2 に答える 2

2

Visual Studioを使用してプログラムをデバッグし、プロジェクトにDLLを含める場合(Visual Studio 2012 Express Editionでは、ソリューションにさまざまな種類のプロジェクトを含めることができます)、[ネイティブコードのデバッグを許可する]オプションを設定して、デバッガーをDLLから関数をP/呼び出しする場合のVB.NETからC++へ。

これが実用的な概念実証です。解凍し、Visual Studioで開いて、ビルドして実行するだけです。このプログラムをプロジェクトと比較して違いを見つけ、コードが失敗する可能性があります。

DLLから関数を実際にエクスポートしていないと思います。DLLのコードに含めるだけでは不十分な場合があります。DependencyWalker他のリンク)プログラムを使用してDLLからエクスポートされる関数を確認してください。たとえば、次の宣言を追加する必要がありました。

__declspec(dllexport) int __stdcall Test() { ... }

さらに、装飾されないエクスポートされた関数の名前の.defファイルを作成します。

DLLソースコードを変更し、関数宣言を次のように変更してみてください。

extern "C" __declspec(dllexport) int hello()
{
  return 1;
}  
于 2013-03-01T11:02:55.430 に答える
2

DeclareVB6レガシーです。p/invoke と DllImport 属性を使用する必要があります。

<DllImport("mydll.dll", CallingConvention:=CallingConvention.Cdecl)> _
Public Shared Function hello() As Integer
End Function

これが失敗する可能性がある方法はたくさんあります。32/64 ビットの不一致があるため、DLL がロードされていない可能性があります。また、呼び出し規約が一致しません。DLL は cdecl を使用しますが、VB コードは stdcall を使用します。上記のピンボークはそれを修正します。

最も深刻なのは、関数が DLL からエクスポートされたように見えないことです。それだと確実に失敗します。Dependency Walker を使用して、関数がエクスポートされているかどうかを判断します。私は g++ にあまり詳しくないので、GNU ツールチェーンを使用して関数をエクスポートする方法を理解する必要があります。ただし、名前の装飾と名前のマングルには注意してください。関数が目的の名前でエクスポートされるように、関数のエクスポート方法に注意する必要がある場合があります。

于 2013-03-01T11:11:42.873 に答える