您当前的位置: 首页 > 

插件开发

暂无认证

  • 1浏览

    0关注

    492博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

illustrator插件开发-AI插件-aip格式-第一章 第二小节 入口点函数

插件开发 发布时间:2022-04-10 07:24:01 ,浏览量:1

文章目录
    • 1.入口点函数
    • 2.作者答疑

1.入口点函数

  插件作为illustrator软件的一部分,需要与主体程序进行通信,必然需要约定调用函数。而入口点函数就是其中关键一环,实例代码如下:

/** Basic suite-access information provided with every call. */
struct SPMessageData {
#ifdef __cplusplus
	SPMessageData(ai::int32 SPCheck_ = 0, struct SPPlugin *self_ = 0, void *globals_ = 0, struct SPBasicSuite *basic_ = 0)
	:	SPCheck(SPCheck_), self(self_), globals(globals_), basic(basic_) {}
#endif

	/** \c #kSPValidSPMessageData if this is a valid PICA message. */
	ai::int32 SPCheck;
	/** This plug-in, an \c #SPPluginRef. */
	struct SPPlugin *self;
	/** An array of application-wide global variables. */
	void *globals;
	/** A pointer to the basic PICA suite, which you use to obtain all other suites. */
	struct SPBasicSuite *basic;
};

extern "C" ASAPI ASErr PluginMain(char* caller, char* selector, void* message)
{
	//caller指示消息的发送者(PICA,宿主程序或插件)和动作的通用类型。
	//selector指定动作类型的执行动作。所有插件收到至少4类消息动作:reload(重新加载),unload(卸载),startup(启动)和shutdown(关系)。此外,插件可能收到特定插件类型的附加消息。
	//message指针是一个消息数据结构体,它包括这个消息动作的相关信息。如,当一个鼠标点击消息接收到时,消息结构体包括鼠标的位置。消息结构体的内容取决于消息,在你的插件定义这个后,才能知道。由于消息内容不同,按照约定,所有消息结构体由相同字段组成,组合到SPMessageData结构体中。
	ASErr error = kNoErr;
	SPMessageData *msgData = (SPMessageData *)message;
	
	Plugin *plugin = (Plugin *)msgData->globals;
	
	sSPBasic = msgData->basic;
	
	/** PICA messaging system caller; see \c #SPInterfaceSuite. */
	//#define kSPInterfaceCaller				"SP Interface"
	if (strcmp(caller, kSPInterfaceCaller) == 0) //是否是消息系统调用
	{	
		/** PICA messaging system startup; see \c #SPInterfaceSuite.  */
		//#define kSPInterfaceStartupSelector		"Startup"
		if (strcmp( selector, kSPInterfaceStartupSelector) == 0)//插件启动
		{
			plugin = AllocatePlugin(msgData->self);//全局插件
			if (plugin)
			{
				msgData->globals = (void *)plugin;
				error = plugin->StartupPlugin((SPInterfaceMessage *)message);//插件启动

				if (error != kNoErr)
				{
					// Make sure to delete in case startup failed
					delete plugin;
					plugin = nil;
					msgData->globals = nil;
				}
			}
			else
			{
				error = kOutOfMemoryErr;
			}
		}
		else if (strcmp(selector, kSPInterfaceShutdownSelector) == 0)// 插件关闭
		{
			if (plugin)
			{
				error = plugin->ShutdownPlugin((SPInterfaceMessage *)message);//关闭函数			
				delete plugin;
				plugin = nil;
				msgData->globals = nil;
			}
		}
	}
	
	if (plugin)
	{
		if (Plugin::IsReloadMsg(caller, selector))//重载插件
		{
			// Call this before calling any virtual functions (like Message)
			FixupReload(plugin);
			error = plugin->ReloadPlugin((SPInterfaceMessage *)message);
		}
		else
		{
			// If a load or reload failed because the suites could not be acquired, we released
			// any partially acquired suites and returned an error.  However, SuitePea still might
			// call us, so protect against this situation.
			if (plugin->SuitesAcquired())
				error = plugin->Message(caller, selector, message);//消息路由
			else
				error = kNoErr;
		}

		if (error == kUnhandledMsgErr)
		{
			error = kNoErr;
#ifndef NDEBUG
#ifdef MAC_ENV
			fprintf(stderr, "Warning: Unhandled plugin message: caller \"%s\" selector \"%s\"\n", caller, selector);
#else
			char buf[1024];
			
			sprintf(buf+1, "Warning: Unhandled plugin message: caller \"%s\" selector \"%s\"\n", caller, selector);
			OutputDebugStringA(buf+1);
#endif
#endif
		}
	}	

	if (error)
	{
		if (plugin)
			plugin->ReportError(error, caller, selector, message);//错误
		else
			Plugin::DefaultError(msgData->self, error);
	}
	
	return error;
}

  功能解析都写在注释里,方便读者阅读,在上述入口函数中,涉及到了两个类一个是SPMessageData,它里面有几个参数,见注释,另一个是SPBasicSuite类,代码如下所示:

/*******************************************************************************
 **
 **	Suite
 **
 **/

/** @ingroup Suites
	This suite provides basic memory management for PICA (the Adobe plug-in manager)
	and defines the basic functions for acquiring and releasing other suites.

	A suite consists of a list of function pointers. The application, or a
	plug-in that loads a suite, provides valid pointers when the suite is
	acquired. When a suite is not available, the pointers are set to the
	address of the \c #Undefined() function.

	Do not attempt to acquire a suite (other than the \c #SPBlocksSuite)
	in response to a PICA access (\c #kSPAccessCaller) or property
	(\c #kSPPropertiesCaller) message. Most suites are unavailable
	during these load and unload operations.

	You can acquire all the suites you will need when your plug-in is first
	loaded, as long as you release them before your plug-in is unloaded.
	At shutdown, however, it is most efficient to acquire only those
	suites explicitly needed to shut down; for example, to free memory
	and save preferences.

	The \c SPBasicSuite itself is a part of the message data passed
	to your plug-in with any call. To access it from the message data structure:
	@code
	SPBasicSuite sBasic = message->d.basic;
	sBasic->function( )
	@endcode
	*/
typedef struct SPBasicSuite {
	/** Acquires a function suite. Loads the suite if necessary,
		and increments its reference count. For example:
	@code
SPErr error;
SPBasicSuite *sBasic = message->d.basic;
AIRandomSuite *sRandom;
sBasic->AcquireSuite( kAIRandomSuite, kAIRandomVersion, &sRandom );
	@endcode
			@param name The suite name.
			@param version The suite version number.
			@param suite [out] A buffer in which to return the suite pointer.
			@see \c #SPSuitesSuite::AcquireSuite()
		*/
	SPAPI SPErr (*AcquireSuite)( const char *name, ai::int32 version, const void **suite );
	/** Decrements the reference count of a suite and unloads it when the
		reference count reaches 0.
			@param name The suite name.
			@param version The suite version number.
		*/
	SPAPI SPErr (*ReleaseSuite)( const char *name, ai::int32 version );
	/** Compares two strings for equality.
			@param token1 The first null-terminated string.
			@param token2 The second null-terminated string.
			@return True if the strings are the same, false otherwise.
		*/
	SPAPI SPBoolean (*IsEqual)( const char *token1, const char *token2 );
	/** Allocates a block of memory.
			@param size The number of bytes.
			@param block [out] A buffer in which to return the block pointer.
			@see \c #SPBlocksSuite::AllocateBlock()
		*/
	SPAPI SPErr (*AllocateBlock)( size_t size, void **block );
	/** Frees a block of memory allocated with \c #AllocateBlock().
			@param block The block pointer.
			@see \c #SPBlocksSuite::FreeBlock()
		*/
	SPAPI SPErr (*FreeBlock)( void *block );
	/** Reallocates a block previously allocated with \c #AllocateBlock().
		Increases the size without changing the location, if possible.
			@param block The block pointer.
			@param newSize The new number of bytes.
			@param newblock [out] A buffer in which to return the new block pointer.
			@see \c #SPBlocksSuite::ReallocateBlock()
		*/
	SPAPI SPErr (*ReallocateBlock)( void *block, size_t newSize, void **newblock );
 	/** A function pointer for unloaded suites. This is a protective measure
 		against other plug-ins that may mistakenly use the suite after they have
 		released it.

 		A plug-in that exports a suite should unload the suite's procedure pointers
 		when it is unloaded, and restore them when the plug-in is reloaded.
 		\li On unload, replace the suite's procedure pointers
 			with the address of this function.
		\li On reload, restore the suite's procedure
			pointers with the updated addresses of their functions.

		For example:
	@code
	 	SPErr UnloadSuite( MySuite *mySuite, SPAccessMessage *message ) {
	 		mySuite->functionA = (void *) message->d.basic->Undefined;
	 		mySuite->functionB = (void *) message->d.basic->Undefined;
	 	}

	 	SPErr ReloadSuite( MySuite *mySuite, SPAccessMessage *message ) {
	 		mySuite->functionA = functionA;
	 		mySuite->functionB = functionB;
	 	}
	@endcode
		*/
	SPAPI SPErr (*Undefined)( void );

} SPBasicSuite;

  这是一个加载模块,它实现了模块的加载和卸载,还有内存分配、释放和重新分配功能。

2.作者答疑

  如有疑问,请留言。

关注
打赏
1665481431
查看更多评论
立即登录/注册

微信扫码登录

0.1020s