Jump to content
Markk

Argument being passed as nil to original function when post-hooking

Recommended Posts

Just made a mock-up addon to show how I have it set up (I've tested this code too and the problem persists)

This file loads first based on ordering in .toc:

Spoiler

MTweaks = {};

function MTweaks:TestFunction(str)
	if (str ~= nil) then
		ChatFrame1:AddMessage("|cff408cff[Original] object = |cff7fff7f"..str);
	else
		ChatFrame1:AddMessage("|cff408cff[Original] object = |cffab1111nil");
	end

	if str == "TestArg" then
		-- Stuff would happen...
	else
		-- Different stuff would happen...
	end
end

function MTweaks:OnLoad()
	MTweaksEventFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
end

function MTweaks:OnEvent()
	if (event == "PLAYER_ENTERING_WORLD") then
		MTweaks:TestFunction();
		MTweaks:TestFunction("TestArg");
	end
end

 

This one loads after the above:

Spoiler

function MTweaks:PostHook(num1, num2, num3, str)
	if (str ~= nil) then
		ChatFrame1:AddMessage("|cffffff9a[PostHook] object = |cff7fff7f"..str.."|cffffff9a | "..num1..", "..num2..", "..num3);
	else
		ChatFrame1:AddMessage("|cffffff9a[PostHook] object = |cffab1111nil|cffffff9a | "..num1..", "..num2..", "..num3);
	end

	if str == "TestArg" then
		-- Stuff would happen after TestFunction...
	else
		-- Different stuff would happen after TestFunction...
	end
end

local originalTestFunction = MTweaks.TestFunction;
function MTweaks:TestFunction(str)
	if (str ~= nil) then
		ChatFrame1:AddMessage("|cffef6030[Altered] object = |cff7fff7f"..str);
	else
		ChatFrame1:AddMessage("|cffef6030[Altered] object = |cffab1111nil");
	end

	originalTestFunction(str);
	MTweaks:PostHook(200, 100, 300, str);
end

 

I have an XML too, but it doesn't do anything except create a dummy frame to call the event functions.

Here is the output of the chat messages:

rLwSdsE.png

The second call doesn't pass "TestArg" to the original function, but it does pass it to the post hook. What's going on here? This is not how I expect it to behave.

Share this post


Link to post
Share on other sites
	originalTestFunction(_, str);

or

MTweaks.originalTestFunction = MTweaks.TestFunction;
function MTweaks:TestFunction(str)
	...
	MTweaks:originalTestFunction(str);

 

Edited by gashole

Share this post


Link to post
Share on other sites

This is a common gotcha for Lua newcomers! Let me explain:

When you have a method like this:

function SomeTable:SomeFunction(arg)

end

it is essentially a shorthand for this:

SomeTable.SomeFunction = function(self, arg)

end

 

In case you have a C++ background, you can see the "self" as the "this pointer" that also gets implicitly passed to a method when you call it.

 

So in order to fix it, you'd have to call the original function like this:

local hookedFunction = SomeTable.OriginalFunction;
function SomeTable:HookedCall(arg)
    hookedFunction(self, arg)
end

 

 

 

Edit:

@gashole:

No, your first example is wrong. With your code:

local Table = {}

function Table:OriginalFunction(arg)
    self:SomeOtherFunction(arg) -- uh oh!
end

local hookedFunction = Table.OriginalFunction;
function Table:HookedCall(arg)
    hookedFunction(event, arg)
end
Table.OriginalFunction = Table.HookedCall

-- then inside an event handler

Table:OriginalFunction("this will break!")

 

Since "Table.OriginalFunction" expects "Table" as its first argument, you'd get an error because "event" isn't said table.

Edited by Ike

Share this post


Link to post
Share on other sites


@Ike so if I changed all functions to

SomeTable.SomeFunction = function(arg)

, without the self in the parameters, it would work too? It's just the function shorthand that adds the self parameter?

Share this post


Link to post
Share on other sites
1 minute ago, Markk said:


@Ike so if I changed all functions to


SomeTable.SomeFunction = function(arg)

, without the self in the parameters, it would work too? It's just the function shorthand that adds the self parameter?

 

Sure, you could also do it like that. Personally, I'd just pass the "self" down to the hook, however. 

Share this post


Link to post
Share on other sites
30 minutes ago, Ike said:

...

Since "Table.OriginalFunction" expects "Table" as its first argument, you'd get an error because "event" isn't said table.

I corrected it; however, "event" can be used in this hooked function without error.

Share this post


Link to post
Share on other sites

No, the first example is still wrong. Look at my original answer.

function Table:Function(arg)
end

is the same thing as

Table.Function = function(self, arg)
end

 

Which means that these two are also identical:

Table:Function("meow")
Table.Function(Table, "meow")

 

Therefore, using the OP's post, the only valid first argument is the table "MTweaks" or its more generic equivalent "self" (since it's used in a "Table:Function" context).

 

While it is true that it wouldn't cause an error in the example Markk posted, it can still later down the line bite him in the ass if he starts calling functions using "self" (e.g. self:Foobar()).

 

In case I don't make much sense (it's 7 am and I haven't had my coffee), here's a link that describes it pretty well:

https://coronalabs.com/blog/2015/12/01/tutorial-understanding-the-colon-vs-dot-operator/

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×