1

このサイトをよく利用していますが、ここで質問するのは初めてです!

しばらく検索した後、これを見つけました: http: //tigerang.blogspot.pt/2008/09/reverse-pinvoke.html

それが私がやりたいことのほとんどだと思います。ここで説明します:(PLZ注私はc++、c#、javaから来ています)私は2つのプロジェクト、アンマネージドc ++とC#WPFアプリを備えたビジュアルスタジオのソリューションを持っています。c ++にはクラスが1つだけあり、OpenCVを使用していくつかの処理を行います。WPFクラスは画像に接続し、いくつかの(x、y)ポイントを取得し、それらをc++に渡す必要があります。その後、WPF側からC ++関数を呼び出し、結果を取得します。

だから私の質問は、ポイントのリスト(リスト)を渡したいのですが、私が見ている例を自分の状況に適応させるのに問題があり、これに関する非常に少ないドキュメントを見つけました(またはおそらく私は初心者ですそして私はそれを見つける/使用する方法がわかりません)。

サンプルコード:C#

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct Ponto
{
    public double x;
    public double y;
}


[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate List<Ponto> CallBackDelegate();



public class ManagedClass
{
    private CallBackDelegate _delegate;



    public List<Ponto> vectorp;

    public ManagedClass()
    {
        _delegate = new CallBackDelegate(this.Foo);
    }

    public CallBackDelegate GetDelegate()
    {
        return _delegate;
    }

    public List<Ponto> Foo()
    {
       //do shit
        Ponto p1 = new Ponto();
        p1.x = 10;
        p1.y = 2;
        Ponto p2 = new Ponto();
        p2.x = 5;
        p2.y = 7;
        Ponto p3 = new Ponto();
        p3.x = 3;
        p3.y = 8;
        vectorp.Add(p1);
        vectorp.Add(p2);
        vectorp.Add(p3);


        return vectorp; 
    }
}

サンプルコードC++;

 #include <iostream>

 #pragma once
 #include <windows.h>
 #include <list>


 #define INTEROPBRIDGE_API __declspec(dllexport)

 INTEROPBRIDGE_API void fnInteropBridge(list<Ponto> data) //IM GETTING ERRORS HERE
 {
     ManagedLib::ManagedClass^ c = gcnew ManagedLib::ManagedClass();
     IntPtr p = Marshal::GetFunctionPointerForDelegate(c->GetDelegate());

     NativeToManaged funcPointer = (NativeToManaged) p.ToPointer();

     // invoke the delegate
     funcPointer(data);
 }


 // data structure for the callback function
 struct Ponto
 {
     double x;
     double y;
 };

 // callback function prototype
 typedef void (*NativeToManaged)(list<Ponto> data);

 using namespace std;
 void main()
 {
   cout << "Hello World!" << endl;   
   cout << "Welcome to C++ Programming" << endl;

 }
4

1 に答える 1

1

System.Collections.Generic.List は C++ の std::list とは完全に異なるため、C++ コードは機能しません。

C++ コードが (現在のように) 管理されている場合は、C# クラスを直接参照するだけです。関数ポインタは必要ありません。

しかし、本当にアンマネージ C++ から C# コードを使用したい場合、最も簡単な方法は COM を使用することです。C# コードを変更する必要があるのは、ManagedClass.Foo を変更して、List ではなく配列を返すようにすることだけです。List は COM から見えないためです。さらに、型にいくつかの属性を追加し、クラスのインターフェイスを追加します。実装する:

[ComVisible(true)]
[Guid("2EF06BCB-A25B-41AD-B233-33A956DBEB69")]
public struct Ponto
{
    public double x;
    public double y;

    public Ponto(double x, double y)
    {
        this.x = x;
        this.y = y;
    }
}

[ComVisible(true)]
[Guid("EB9258F5-DCFB-4F91-8342-5A05EB17557D")]
public interface IManagedClass
{
    Ponto[] Foo();
}

[ComVisible(true)]
[Guid("11B23AD7-F79E-45D7-BC87-89F0DBC8B83F")]
[ClassInterface(ClassInterfaceType.None)]
public class ManagedClass : IManagedClass
{
    private List<Ponto> points;

    public ManagedClass()
    {
        points = new List<Ponto>();
        points.Add(new Ponto(1.0, 1.0));
        points.Add(new Ponto(2.0, 2.0));
        points.Add(new Ponto(3.0, 3.0));
    }

    public Ponto[] Foo()
    {
        return points.ToArray();
    }
}

プロジェクトをビルドし、管理者権限で Visual Studio コマンド プロンプトを起動し、次のようなコマンドを使用してアセンブリのタイプ ライブラリをエクスポートし、登録します。

regasm ManagedAssembly.dll /tlb:ManagedAssembly.tlb /コードベース

そして、C++ コードはそれを次のように消費します。

#import "ManagedAssembly.tlb"
#include <iostream>

using namespace ManagedAssembly;
using namespace std;

int main()
{
    ::CoInitialize(NULL);

    {
        IManagedClassPtr pManagedClass(__uuidof(ManagedClass));

        SAFEARRAY* psa = pManagedClass->Foo();
        Ponto* pPoints = (Ponto*)psa->pvData;

        for (int i = 0; i < 3; ++i)
            cout << pPoints[i].x << " " << pPoints[i].y << endl;
    }

    ::CoUninitialize();
}
于 2013-03-07T05:30:45.473 に答える