DLL Exception when set array

I want to convert "for" loop to C++, but I get an exception when I set value to setArray.array[i].

image

AmiVar myFunc2b(int NumArgs, AmiVar* ArgsTable)
{
	AmiVar setArray = gSite.AllocArrayResult();
	AmiVar result = gSite.AllocArrayResult();
	int nSize = gSite.GetArraySize();// barcount

//GetVariable from AFL
	AmiVar newDay = gSite.GetVariable("newDay");
	AmiVar sigBuy = gSite.GetVariable("sigBuy");

	float* sumArgsList = new float[nSize];

	for (int i = 10000; i < nSize; i++)
	{
		if (sigBuy.array[i-1] && newDay.array[i])
		{
			setArray.array[i] = 1;
			continue;
		}
	}
	gSite.SetVariable("Buy", setArray);

	result.val = 1;
	result.type = VAR_FLOAT;
	return result;
}

AFL with use DLL:

newDay=Day()!=Ref(Day(),-1);
sigBuy=0;

dll1=myFunc2b();

Any idea?

If you are calling GetVariable, you can't ASSUME that it is array. It can be scalar and if it is, you are accessing array that does not exist and creating access violation. sigBuy in your AFL is exactly that - SCALAR value, not array.

I understand that I have to use sigBuy as ArgsTable's argument, buy how can I use GetVariable like array?

You have to check whether variable is type array.

OK, I understand now. In my full code, "sigBuy" is an array, not scalar. It changes things.

No, you don't understand at all.
In your C code you have to programmatically check for type array of variable so that you do not ever get exception in case variable is not type array.

You make explicit SCALAR assignment in your AFL formula

sigBuy = 0; // 0 IS A SCALAR !!!

You must NEVER use AmiVar .array field UNLESS you verify if .type is VAR_ARRAY

In your plugin you are doing this:

AmiVar sigBuy = gSite.GetVariable("sigBuy");

And sigBuy is a SCALAR value and you can ONLY access .val field, not .array.

Only if you assigned ARRAY to sigBuy, like this:

sigBuy = Cross( C, MA( C, 10 ) ); // sigBuy is truly an array

you would have type == VAR_ARRAY and you could access .array

Really writing PLUGINS IS HIGHLY DISCOURAGED because 99.9% of people "don't get it right"

AFL is whole lot easier since it does automatic type coercion hiding all details and problems, see: When scalar becomes an array, aka. type coercion in AFL but in C/C++ you are in unknown dangerous waters and no one is protecting you from evil :slight_smile:

3 Likes

Sorry for that, but I have a new problem.
If I don't use global variable for arrays, I get an exception from plugin.

function fnTest()
{
	global up,down;

    up = Open * 1.20;
    down = Open * 0.80;

    cplus = LoopCplus();
}

fun = fnTest();

AmiVar VLoopCplus(int NumArgs, AmiVar* ArgsTable)
{
	int i, j;
	int nSize = gSite.GetArraySize();
	
	AmiVar result = gSite.AllocArrayResult();

	AmiVar up = gSite.GetVariable("up");
	AmiVar down = gSite.GetVariable("down");

	AmiVar varset = gSite.AllocArrayResult();

	float* open = gSite.GetStockArray(0);
	float* close = gSite.GetStockArray(3);

	for (i = 0; i < nSize; i++)
	{
			if (close[i] < open[i - 1])
			{
				varset.array[i] = down.array[i];
			}
			else
			{
				varset.array[i] = up.array[i];
			}
	}
	
	result.val = 1;
	result.type = VAR_ARRAY;
	return result;
}

You are getting exception because you are doing BAD things, namely accessing NON-existing variable. Local variable does NOT have global name and if you attempt to access it via GetVariable you would get nothing. You are NOT doing necessary checks in your code and make ASSUMPTIONS (really bad thing). You should NEVER assume that any variable exists and you should ALWAYS check what you are getting from GetVariable.

GetVariable by design accesses GLOBAL variables because it operates in global namespace. If you want to access local values, PASS THEM as arguments to the function exposed by DLL.

Again, writing plugins is DISCOURAGED because most people don't do it right. This thread illustrates this.

Specifically using GetVariable is BAD PRACTICE. You should be passing values AS ARGUMENTS to DLL exposed function. Why it is bad practice ? Because it produces hidden relationships between plugin and AFL code instead of clearly defined API by means of arguments passed to the function.

5 Likes