PDA

View Full Version : Where do you put native lists when writing extentions?


ILikePizza555
08-13-2012, 23:58
I wasn't sure where to put this, so I settled on here. If it it's the wrong section, please point in the right direction.

Anyways, I've been trying to make a sourcemod exention, and I have been following the somewhat outdated information on the wiki. Everything was going fine until I got to the "Binding" part of tutorial. The wiki gives me this:

const sp_nativeinfo_t MyNatives[] = { {"SquareNumber", SquareNumber}, {NULL, NULL}, };But I have no where to put it! Anywhere I put will either generate a
error C2065: 'randNum' : undeclared identifieror a
error C2440: 'initializing' : cannot convert from 'cell_t (__thiscall Ext_Object::* )(SourcePawn::IPluginContext *,const cell_t *)' to 'SPVM_NATIVE_FUNC'I'm completely stuck here, any help? :?:

Powerlord
08-14-2012, 08:43
In my only extension, my natives are declared in the header of my natives.h file. I intentionally have natives in a separate file from the actual method calls.

For instance, this is in my natives.h:

const sp_nativeinfo_t g_Natives[] =
{
{"CreateBuiltinVote", CreateBuiltinVote},
{"DisplayBuiltinVote", DisplayBuiltinVote},
{"AddBuiltinVoteItem", AddBuiltinVoteItem},
{"InsertBuiltinVoteItem", InsertBuiltinVoteItem},
{"RemoveBuiltinVoteItem", RemoveBuiltinVoteItem},
{"RemoveAllBuiltinVoteItems", RemoveAllBuiltinVoteItems},
{"GetBuiltinVoteItem", GetBuiltinVoteItem},
{"GetBuiltinVoteItemCount", GetBuiltinVoteItemCount},
{"SetBuiltinVoteArgument", SetBuiltinVoteArgument},
{"GetBuiltinVoteArgument", GetBuiltinVoteArgument},
{"IsBuiltinVoteInProgress", IsBuiltinVoteInProgress},
// {"GetBuiltinVoteStyle", GetBuiltinVoteStyle},
// {"GetBuiltinVoteStyleHandle", GetBuiltinVoteStyleHandle},
{"GetBuiltinVoteMaxItems", GetBuiltinVoteMaxItems},
{"GetBuiltinVoteOptionFlags", GetBuiltinVoteOptionFlags},
{"SetBuiltinVoteOptionFlags", SetBuiltinVoteOptionFlags},
{"CancelBuiltinVote", CancelBuiltinVote},
{"SetBuiltinVoteResultCallback", SetBuiltinVoteResultCallback},
{"CheckBuiltinVoteDelay", CheckBuiltinVoteDelay},
// {"GetBuiltinVoteSelectionPosition", GetBuiltinVoteSelectionPosition},
{"IsClientInBuiltinVotePool", IsClientInBuiltinVotePool},
{"RedrawClientBuiltinVote", RedrawClientBuiltinVote},
{"GetBuiltinVoteType", GetBuiltinVoteType},
{"SetBuiltinVoteTeam", SetBuiltinVoteTeam},
{"GetBuiltinVoteTeam", GetBuiltinVoteTeam},
{"SetBuiltinVoteInitiator", SetBuiltinVoteInitiator},
{"GetBuiltinVoteInitiator", GetBuiltinVoteInitiator},
{"DisplayBuiltinVotePass", DisplayBuiltinVotePass},
{"DisplayBuiltinVotePass2", DisplayBuiltinVotePass2},
{"DisplayBuiltinVoteFail", DisplayBuiltinVoteFail},
{NULL, NULL},
};Note that each method on the right side is also declared in natives.h and all of them have identical signatures, like this:

cell_t DisplayBuiltinVoteFail(IPluginContext *pContext, const cell_t *params);My natives are registered in extension.cpp:

void BuiltinVoteManager::SDK_OnAllLoaded()
{
// Load natives
sharesys->AddNatives(myself, g_Natives);
}

natives.h is included from extension.h.

ILikePizza555
08-14-2012, 11:24
In my only extension, my natives are declared in the header of my natives.h file. I intentionally have natives in a separate file from the actual method calls.

For instance, this is in my natives.h:

const sp_nativeinfo_t g_Natives[] =
{
{"CreateBuiltinVote", CreateBuiltinVote},
{"DisplayBuiltinVote", DisplayBuiltinVote},
{"AddBuiltinVoteItem", AddBuiltinVoteItem},
{"InsertBuiltinVoteItem", InsertBuiltinVoteItem},
{"RemoveBuiltinVoteItem", RemoveBuiltinVoteItem},
{"RemoveAllBuiltinVoteItems", RemoveAllBuiltinVoteItems},
{"GetBuiltinVoteItem", GetBuiltinVoteItem},
{"GetBuiltinVoteItemCount", GetBuiltinVoteItemCount},
{"SetBuiltinVoteArgument", SetBuiltinVoteArgument},
{"GetBuiltinVoteArgument", GetBuiltinVoteArgument},
{"IsBuiltinVoteInProgress", IsBuiltinVoteInProgress},
// {"GetBuiltinVoteStyle", GetBuiltinVoteStyle},
// {"GetBuiltinVoteStyleHandle", GetBuiltinVoteStyleHandle},
{"GetBuiltinVoteMaxItems", GetBuiltinVoteMaxItems},
{"GetBuiltinVoteOptionFlags", GetBuiltinVoteOptionFlags},
{"SetBuiltinVoteOptionFlags", SetBuiltinVoteOptionFlags},
{"CancelBuiltinVote", CancelBuiltinVote},
{"SetBuiltinVoteResultCallback", SetBuiltinVoteResultCallback},
{"CheckBuiltinVoteDelay", CheckBuiltinVoteDelay},
// {"GetBuiltinVoteSelectionPosition", GetBuiltinVoteSelectionPosition},
{"IsClientInBuiltinVotePool", IsClientInBuiltinVotePool},
{"RedrawClientBuiltinVote", RedrawClientBuiltinVote},
{"GetBuiltinVoteType", GetBuiltinVoteType},
{"SetBuiltinVoteTeam", SetBuiltinVoteTeam},
{"GetBuiltinVoteTeam", GetBuiltinVoteTeam},
{"SetBuiltinVoteInitiator", SetBuiltinVoteInitiator},
{"GetBuiltinVoteInitiator", GetBuiltinVoteInitiator},
{"DisplayBuiltinVotePass", DisplayBuiltinVotePass},
{"DisplayBuiltinVotePass2", DisplayBuiltinVotePass2},
{"DisplayBuiltinVoteFail", DisplayBuiltinVoteFail},
{NULL, NULL},
};Note that each method on the right side is also declared in natives.h and all of them have identical signatures, like this:

cell_t DisplayBuiltinVoteFail(IPluginContext *pContext, const cell_t *params);My natives are registered in extension.cpp:

void BuiltinVoteManager::SDK_OnAllLoaded()
{
// Load natives
sharesys->AddNatives(myself, g_Natives);
}natives.h is included from extension.h.


I tried what you said: Put the native list in a seperate header file, add the function prototype at the top of the file, include it in extenstion.h, and the load it.

It gets past compiling, but when it's creating the library I'm getting:

error LNK2001: unresolved external symbol "int __cdecl randNum(class SourcePawn::IPluginContext *,int const *)" (?randNum@@YAHPAVIPluginContext@SourcePawn@@P BH@Z)
1>C:\Users\asus\Desktop\Tf2 Stuff\ARaLS\Object\src\msvc10\Release\sample. ext.dll : fatal error LNK1120: 1 unresolved externals

...What?

Powerlord
08-14-2012, 12:36
OK, you moved the native declarations to natives.h, but is the code for the natives in natives.cpp? You might have problems if it isn't.

Side note: C++ needs better error messages.

ILikePizza555
08-14-2012, 12:44
Not sure what you mean by "code for the natives in natives.cpp."

This is the contents of my natives.h file:
#include "smsdk_ext.h"

cell_t randNum(IPluginContext *pContext, const cell_t *params);

const sp_nativeinfo_t g_Natives[] =
{
{"randNum", randNum},
{NULL, NULL},
};

extension.h:
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_

/**
* @file extension.h
* @brief Sample extension code header.
*/

#include "smsdk_ext.h"
#include "natives.h"


/**
* @brief Sample implementation of the SDK Extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
*/
class Ext_Object : public SDKExtension
{
public:
/**
* @brief This is called after the initial loading sequence has been processed.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @param late Whether or not the module was loaded after map load.
* @return True to succeed loading, false to fail.
*/
//virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);

/**
* @brief This is called right before the extension is unloaded.
*/
//virtual void SDK_OnUnload();

/**
* @brief This is called once all known extensions have been loaded.
* Note: It is is a good idea to add natives here, if any are provided.
*/
virtual void SDK_OnAllLoaded();

/**
* @brief Called when the pause state is changed.
*/
//virtual void SDK_OnPauseChange(bool paused);

/**
* @brief this is called when Core wants to know if your extension is working.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @return True if working, false otherwise.
*/
//virtual bool QueryRunning(char *error, size_t maxlength);

cell_t randNum(IPluginContext *pContext, const cell_t *params);

public:
#if defined SMEXT_CONF_METAMOD
/**
* @brief Called when Metamod is attached, before the extension version is called.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @param late Whether or not Metamod considers this a late load.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);

/**
* @brief Called when Metamod is detaching, after the extension version is called.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);

/**
* @brief Called when Metamod's pause state is changing.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param paused Pause state being set.
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
#endif
};

#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_


and extension.cpp
#include "extension.h"

/**
* @file extension.cpp
* @brief Implement extension code here.
*/

cell_t Ext_Object::randNum(IPluginContext *pContext, const cell_t *params)
{
return 70 * 2;
}

void Ext_Object::SDK_OnAllLoaded()
{
sharesys->AddNatives(myself, g_Natives);
}

Ext_Object g_Obj; /**< Global singleton for extension's main interface */

SMEXT_LINK(&g_Obj);

asherkin
08-14-2012, 12:58
Your issue is that you're declaring it has a member function, but natives need to be a top-level method.
The linker error is because you've forward-declared a function with the correct prototype, but it has no implementation.

I suggest reading over some of the existing extensions out there for examples.

Side note: C++ needs better error messages.
The error messages are great.

ILikePizza555
08-14-2012, 13:35
Your issue is that you're declaring it has a member function, but natives need to be a top-level method.
The linker error is because you've forward-declared a function with the correct prototype, but it has no implementation.

I suggest reading over some of the existing extensions out there for examples.


The error messages are great.

Thanks asherkin, I tried it and it works. Now I can continue with the tutorial. :)