Не удается зарегистрировать плагин FMOD на iOS (с использованием Unity3d)
Я создал плагин FMOD на C++ и создал динамическую библиотеку (.dylib) и статическую библиотеку (.a).
Я могу успешно использовать динамическую библиотеку с FMOD Studio GUI, а также я могу использовать ее в симуляторе Unity3d Mac (который выбирает динамическую библиотеку из Assets/Plugins. Но у меня возникают проблемы с работой на iPhone.
Для iOS мне нужно использовать статическую библиотеку (*.a), что означает, что мне нужно вручную загрузить плагин в Unity3d (C#), сгенерировать проект Xcode и установить его на iPhone. Я попытался реализовать базовую функцию в C и загрузить ее на C#, и она отлично работает. Это означает, что статическая библиотека генерируется правильно, и я могу успешно загрузить ее на iPhone и использовать. Но я не могу заставить работать функцию описания FMOD.
Вот мой код, когда я запускаю его на iPhone, я получаю эту ошибку:
"FmodDescPtr - это IntPtr.Zero"
Заранее спасибо за вашу помощь! Я боролся с этим в течение 5 дней и не смог решить его.
Сторона C++:
F_DECLSPEC F_DLLEXPORT int F_STDCALL AigooGetDSPDescription2(FMOD_DSP_DESCRIPTION *FmodDesc)
{
// defines the user interface, maximum distance knob
static float distance_mapping_values[] = { 0, 1, 5, 20, 100, 500, 10000 };
static float distance_mapping_scale[] = { 0, 1, 2, 3, 4, 4.5, 5 };
// defines the 3D location attributes
FMOD_DSP_INIT_PARAMDESC_DATA(p_3d_attributes, "3D Attributes", "", "", FMOD_DSP_PARAMETER_DATA_TYPE_3DATTRIBUTES);
FMOD_DSP_DESCRIPTION Aigoo_Simple_Plugin_Desc =
{
FMOD_PLUGIN_SDK_VERSION,
"AigooSimplePlugin6", // name
0x00010000, // plug-in version
1, // number of input buffers to process
1, // number of output buffers to process
Aigoo_Simple_Plugin_dspcreate,
Aigoo_Simple_Plugin_dsprelease,
Aigoo_Simple_Plugin_dspreset,
Aigoo_Simple_Plugin_dspread,
0,
0,
AIGOO_SIMPLE_PLUGIN_NUM_PARAMETERS,
Aigoo_Simple_Plugin_dspparam,
Aigoo_Simple_Plugin_dspsetparamfloat,
0, // Aigoo_Simple_Plugin_dspsetparamint,
0, // Aigoo_Simple_Plugin_dspsetparambool,
Aigoo_Simple_Plugin_dspsetparamdata,
Aigoo_Simple_Plugin_dspgetparamfloat,
0, // Aigoo_Simple_Plugin_dspgetparamint,
0, // Aigoo_Simple_Plugin_dspgetparambool,
Aigoo_Simple_Plugin_dspgetparamdata,
Aigoo_Simple_Plugin_shouldiprocess,
0, // userdata
Aigoo_Simple_Plugin_sys_register,
Aigoo_Simple_Plugin_sys_deregister,
Aigoo_Simple_Plugin_sys_mix
};
FmodDesc = &Aigoo_Simple_Plugin_Desc;
return 9291983; //this is to test that I'm able to get this value on C# and iOS side
}
Сторона C#:
public class AigooPlugInHandler {
[DllImport ("__Internal")]
public static extern int AigooGetDSPDescription2(out IntPtr FmodDesc);
}
public class MyAigooClass : MonoBehaviour
{
if (Application.platform == RuntimePlatform.IPhonePlayer) {
IntPtr FmodDescPtr;
plugin_result = AigooPlugInHandler.AigooGetDSPDescription2(out FmodDescPtr);
//printing plugin_result returns 9291983 which is the value returned from C
if (FmodDescPtr != IntPtr.Zero)
{
DSP_DESCRIPTION FmodDesc = (DSP_DESCRIPTION)Marshal.PtrToStructure(FmodDescPtr, typeof(DSP_DESCRIPTION));
FmodDesc.numinputbuffers = 1;
ERRCHECK(sys.registerDSP(ref FmodDesc, out mmdsp_handle));
}
else
Console.WriteLine("FmodDescPtr is IntPtr.Zero");
}
}
Это оригинальная структура для DSP_DESCRIPTION:
[StructLayout(LayoutKind.Sequential)] //original:
public struct DSP_DESCRIPTION
{
public uint pluginsdkversion; /* [w] The plugin SDK version this plugin is built for. set to this to FMOD_PLUGIN_SDK_VERSION defined above. */
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public char[] name; /* [w] Name of the unit to be displayed in the network. */
public uint version; /* [w] Plugin writer's version number. */
public int numinputbuffers; /* [w] Number of input buffers to process. Use 0 for DSPs that only generate sound and 1 for effects that process incoming sound. */
public int numoutputbuffers; /* [w] Number of audio output buffers. Only one output buffer is currently supported. */
public DSP_CREATECALLBACK create; /* [w] Create callback. This is called when DSP unit is created. Can be null. */
public DSP_RELEASECALLBACK release; /* [w] Release callback. This is called just before the unit is freed so the user can do any cleanup needed for the unit. Can be null. */
public DSP_RESETCALLBACK reset; /* [w] Reset callback. This is called by the user to reset any history buffers that may need resetting for a filter, when it is to be used or re-used for the first time to its initial clean state. Use to avoid clicks or artifacts. */
public DSP_READCALLBACK read; /* [w] Read callback. Processing is done here. Can be null. */
public DSP_PROCESS_CALLBACK process; /* [w] Process callback. Can be specified instead of the read callback if any channel format changes occur between input and output. This also replaces shouldiprocess and should return an error if the effect is to be bypassed. Can be null. */
public DSP_SETPOSITIONCALLBACK setposition; /* [w] Setposition callback. This is called if the unit wants to update its position info but not process data. Can be null. */
public int numparameters; /* [w] Number of parameters used in this filter. The user finds this with DSP::getNumParameters */
public IntPtr paramdesc; /* [w] Variable number of parameter structures. */
public DSP_SETPARAM_FLOAT_CALLBACK setparameterfloat; /* [w] This is called when the user calls DSP.setParameterFloat. Can be null. */
public DSP_SETPARAM_INT_CALLBACK setparameterint; /* [w] This is called when the user calls DSP.setParameterInt. Can be null. */
public DSP_SETPARAM_BOOL_CALLBACK setparameterbool; /* [w] This is called when the user calls DSP.setParameterBool. Can be null. */
public DSP_SETPARAM_DATA_CALLBACK setparameterdata; /* [w] This is called when the user calls DSP.setParameterData. Can be null. */
public DSP_GETPARAM_FLOAT_CALLBACK getparameterfloat; /* [w] This is called when the user calls DSP.getParameterFloat. Can be null. */
public DSP_GETPARAM_INT_CALLBACK getparameterint; /* [w] This is called when the user calls DSP.getParameterInt. Can be null. */
public DSP_GETPARAM_BOOL_CALLBACK getparameterbool; /* [w] This is called when the user calls DSP.getParameterBool. Can be null. */
public DSP_GETPARAM_DATA_CALLBACK getparameterdata; /* [w] This is called when the user calls DSP.getParameterData. Can be null. */
public DSP_SHOULDIPROCESS_CALLBACK shouldiprocess; /* [w] This is called before processing. You can detect if inputs are idle and return FMOD_OK to process, or any other error code to avoid processing the effect. Use a count down timer to allow effect tails to process before idling! */
public IntPtr userdata; /* [w] Optional. Specify 0 to ignore. This is user data to be attached to the DSP unit during creation. Access via DSP::getUserData. */
}
Спасибо Карлос
1 ответ
Похоже Aigoo_Simple_Plugin_Desc
размещается в стеке, а не в куче.
Вместо:
FMOD_DSP_DESCRIPTION Aigoo_Simple_Plugin_Desc = ...
... попробуйте следующее. Обратите внимание, как FMOD_DSP_DESCRIPTION
параметр был изменен на указатель на указатель:
F_DECLSPEC F_DLLEXPORT int F_STDCALL
AigooGetDSPDescription2(FMOD_DSP_DESCRIPTION **ppFmodDesc)
{
FMOD_DSP_DESCRIPTION* Aigoo_Simple_Plugin_DescPtr = new FMOD_DSP_DESCRIPTION ();
// initialise Aigoo_Simple_Plugin_DescPtr
.
.
.
*ppFmodDesc = Aigoo_Simple_Plugin_DescPtr;
.
.
.
Указанная структура должна быть легкодоступной или иметь информацию о макете
Попробуйте добавить [StructLayout(LayoutKind.Explicit)]
к вашей структуре на стороне C#.