よし、これで契約だ。NinjaTrader プラットフォーム用に作成されたインジケーター (ninjascript で作成されています... 基本的に C# にプラットフォーム固有のコードが追加されています) を使用して C++ dll をインターフェイスしようとしています。dll を意図したとおりに動作させるには、構造体配列をインジケーターから dll に渡すことができる必要があります。インジケーター コードでは、ref を介して構造体配列を渡しています。dll では、構造体配列をポインターとして受け入れようとしています。これにより、大量の情報を NinjaTrader に戻す方法を考え出すことなく、dll の内容を編集することができます。基本的に、dll は構造体配列ポインターを受け取り、内容に直接アクセスできるようにします。次に、dll 関数が bool true フラグを Ninja に返すと、struct 配列にアクセスし、情報をチャートにレンダリングします。シンプルですね。私もそう思いました。
これが問題です。NinjaTrader は安全でないコードを許可しません。そのため、構造体配列を dll に渡してポインタとして受け取ろうとすると、すぐにプラットフォームがクラッシュします。構造体配列を ref (*&) へのポインターとして受け取った場合は機能しますが、制御が Ninja に戻されると、構造体配列で行われたすべての編集は存在しなくなります。
そこで、このプロセスを高速化するために、非常に簡単なインジケーターと、私がやろうとしていることを示す dll コード セットを作成しました。忍者インジケータコードは次のとおりです。
[StructLayout(LayoutKind.Sequential)]
public struct TestStruct
{
public int x, y;
}
TestStruct[] test = new TestStruct[2];
protected override void OnBarUpdate()
{
if(CurrentBar < Count - 2) {return;}
test[0].x = 10;
test[0].y = 2;
test[1].x = 0;
test[1].y = 0;
Print(GetDLL.TestFunk(ref test));
Print("X0: " + test[0].x.ToString() + " Y0: " + test[0].y.ToString());
Print("X1: " + test[1].x.ToString() + " Y1: " + test[1].y.ToString());
}
class GetDLL
{
GetDLL() {}
~GetDLL() {}
[DllImport("testdll.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "TestFunk")]
public static extern int TestFunk(
[In,MarshalAs(UnmanagedType.LPArray)] ref TestStruct[] test );
}
そして今、C++ dll コード:
#define WIN32_LEAN_AND_MEAN
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
struct TestStruct
{
int x, y;
};
extern "C" __declspec(dllexport) int __stdcall TestFunk( TestStruct *testy )
{
testy[1].x = 20;
testy[1].y = 9;
int one = testy[1].x;
int two = testy[1].y;
return (one + two);
}
上記で貼り付けたこのコードにより、チャートにインジケーターを配置してアクティブになった瞬間に NinjaTrader がクラッシュすることを覚えておいてください。クラッシュしないようにする唯一の方法は、C++ TestFunk 関数の引数をTestStruct *&testy
orに変更することです。演算子も変更する必要があることTestStruct **testy
に注意してください。.
->
私がすべて言ったので、この制限を回避して実際のポインターにアクセスする方法を知っている人はいますか?クラッシュしない?