【发布时间】:2015-06-20 20:16:17
【问题描述】:
好的,这就是交易。我正在尝试将 C++ dll 与为 NinjaTrader 平台编写的指标接口(它是用 ninjascript 编写的......本质上是 C# 并添加了一些特定于平台的代码)。为了使我的 dll 按预期方式工作,我需要能够将结构数组从指标传递给 dll。在指标代码中,我通过 ref 传递结构数组。在 dll 中,我试图接受 struct 数组作为指针。这使我可以编辑 dll 中的内容,而无需设法将大量信息传回 NinjaTrader。基本上,dll 接收结构数组指针,这使它可以直接访问内容。然后,当 dll 函数向 Ninja 返回一个 bool true 标志时,它会访问 struct 数组并将信息呈现给图表。听起来很简单吧?我也是这么想的。
这就是问题所在。 NinjaTrader 不允许不安全的代码。因此,当我尝试将结构数组传递给 dll 并将其作为指针接收时,它会立即使平台崩溃。如果我接收到 struct 数组作为指向 ref (*&) 的指针,那么它可以工作,但是....一旦将控制权传递回 Ninja,在 struct 数组中完成的所有编辑都不存在。
所以,为了加快这个过程,我创建了一个非常简短的指标和 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 函数中的 arg 更改为 TestStruct *&testy 或 TestStruct **testy,注意 . 运算符也必须更改为 ->。
现在我已经说了这么多,有谁知道如何绕过这个限制并访问实际指针,因此 dll 可以编辑存储在结构数组中的实际值,这将反映在 NinjaTrader 内部。 ..但不会崩溃?
【问题讨论】:
-
必须使用不安全的代码。这是托管 (C#) 和非托管 (C++) 代码之间最大的区别之一,即指针的使用。
-
到目前为止,这就是我的结论。我无法摆脱在 C++ 端可以做一些事情来捕获内存地址的感觉。
-
根据您的约束,您始终可以传递数组或结构,并以您可以轻松执行诸如 returnString.split(',') 之类的格式传回字符串以取回什么你想要/需要。
-
通过该方法返回的数据过多。系统会将其编译为字符串,然后将字符串解码为可用数据,这将对性能造成重大影响。这将破坏用 C++ 对系统进行编码的整个要点,而这几乎完全是为了性能。
-
传递结构体并返回结构体呢?