¡Buenas! Y muchas gracias por adelantado :-[
Tengo un problema que llevo intentando solucionar, sin resultado alguno. Se trata de que estoy intentando ejecutar una DLL propia, creada con VB.NET desde Visual Studio 2012, en Game Maker Studio, pero, obviamente (por estar preguntando) no funciona.
A ver les cuento todo el procedimiento que seguí para crear/ejecutar (o al menos intentarlo D': ) la DLL:
Primero, creé la DLL, siguiendo estos pasos:
1)- Creé un proyecto, como se ve a continuación:
(https://gyazo.com/27cf887d7667c5911b8ce43c234a7367.png)
(Comento que también he intentado creándolo como "Biblioteca de clases portable", con el mismo resultado)
2)- Escribí el código:
Public Class Class1
Public Shared Function prueba() As Object
Return 33
End Function
End Class
(Comento que no sé absolutamente nada de VB.NET, obtuve la estructura de esta web: http://programacionalotico.blogspot.com.co/2010/06/crear-libreria-dll-en-vbnet-y-como.html )
3)- Compilé:
(https://gyazo.com/18acb0cba36be24d515d843e2a6d2283.png)
4)- Moví la DLL obtenida a los Incluided Files de un proyecto en blanco de GMS.
5)- Creé un script, le llamé "prueba". Y en él, apoyándome del manual, escribí esto:
[gml]
var func = external_define("prueba.dll","prueba",dll_stdcall,ty_real,0)
var call = external_call(func);
return call;
[/gml]
6)- En el Creation Code de una room en blanco, escribí esto:
[gml]
a = prueba();
show_message(string(a));
[/gml]
Supongo que al hacer esto, normalmente, se debería mostrar un mensaje emergente con el número 33. Pero, en vez de eso, me muestra un mensaje de error:
___________________________________________
############################################################################################
ERROR in
action number 1
of Create Event
for object <undefined>:
Error defining an external function.
at gml_Script_prueba (line 1) - var func = external_define("prueba.dll","prueba",dll_stdcall,ty_real,0)
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_prueba (line 1)
called from - gml_Room_room0_Create (line 1) - a = prueba();
Inmediatamente después de cerrar la ventana de error, el programa deja de funcionar:
(https://gyazo.com/85b189d58a283a05d3350252b7199569.png)
No tengo idea de por qué sucede este error. He visto extensiones del marketplace que usan este mismo método (aunque la DLL es programada en C++), y no tienen errores.
Muchas gracias de antemano :D
Investigando encontré información que podria serte util, si no has encontrado solucion por tu cuenta haha XD
Al parecer no se puede usar los lenguajes ".net" para crear una dll que funcione con Game Maker. Ha de ser por eso que las dll del Marketplace estan hechas en "c++" ó "c".
Aun asi investigando en internet encontre una "dll" mediadora para poder usar "dll's hechas en .net". Otro punto es que Game Maker no trabaja con numeros int, short, etc., parece funcionar solo con Double, por lo que el "Return 33" te producia el error o eso lei.
Te dejo un .zip adjunto donde esta la dll que menciono y un ejemplo de Game Maker para que veas como funciona, no he tenido tiempo de probarlo asi que no te puedo asegurar que funcione bien.
Muchas gracias por tu ayuda :D
Pero, el error no cambia. Desde que pruebo el editable de GM8 me aparece exactamente el mismo mensaje: "Error defining an external function".
Lo probé en GMS, pero en vez del error anterior, me salen estos:
Citar---------------------------
GM .Net Layer: Unhandled Exception
---------------------------
There has been an unhandled exception in the "GM .Net Layer". The following trace is available:
System.BadImageFormatException: No se puede cargar el archivo o ensamblado 'file:///C:\Users\usuario\AppData\Local\Temp\gm_ttt_93501\gm_ttt_51873\file_write.dll' ni una de sus dependencias. Este ensamblado se creó con un tiempo de ejecución más reciente que el tiempo de ejecución cargado actualmente y no se puede cargar.
Nombre de archivo: 'file:///C:\Users\usuario\AppData\Local\Temp\gm_ttt_93501\gm_ttt_51873\file_write.dll'
en System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
en System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
en System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
en System.Reflection.Assembly.InternalLoadFrom(String assemblyFile, Evidence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm, Boolean forIntrospection, StackCrawlMark& stackMark)
en System.Reflection.Assembly.LoadFrom(String assemblyFile)
en LoadDll(SByte* filename)
AVS: El registro del enlace de ensamblado está desactivado.
Para habilitar el registro de errores del enlace de ensamblado, establezca el valor de Registro [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) como 1.
Nota: existe una disminución del rendimiento asociada registro de errores del enlace de ensamblado.
Para desactivar esta característica, elimine el valor de Registro [HKLM\Software\Microsoft\Fusion!EnableLog].
When seeking support, please contact the creater of the program and copy the complete error message. Press Ctrl+C to copy the message. Press Ok to continue or press Cancel to exit the application.
---------------------------
Aceptar Cancelar
---------------------------
Y éste:
Citar---------------------------
GM .Net Layer: Unhandled Exception
---------------------------
There has been an unhandled exception in the "GM .Net Layer". The following trace is available:
System.NullReferenceException: Referencia a objeto no establecida como instancia de un objeto.
en CreateInstance(Double dll_handle, SByte* fullname)
When seeking support, please contact the creater of the program and copy the complete error message. Press Ctrl+C to copy the message. Press Ok to continue or press Cancel to exit the application.
---------------------------
Aceptar Cancelar
---------------------------
Y éste:
Citar---------------------------
GM .Net Layer: Unhandled Exception
---------------------------
There has been an unhandled exception in the "GM .Net Layer". The following trace is available:
System.NullReferenceException: Referencia a objeto no establecida como instancia de un objeto.
en System.Object.GetType()
en FuncReal(Double class_handle, SByte* funcname)
When seeking support, please contact the creater of the program and copy the complete error message. Press Ctrl+C to copy the message. Press Ok to continue or press Cancel to exit the application.
---------------------------
Aceptar Cancelar
---------------------------
Sólo por si acaso, usé un
Return (en el VB) que devolviera un float (un número con decimal, según tengo entendido), para ver si sucedía algo. Pero no, el mismo error.
Por último, me decidi a echar para atrás la DLL que me pasaste, e intentar crear una en C++, siguiendo esta web:
https://msdn.microsoft.com/es-es/library/ms235636.aspx
Pero el error no ha cambiado en absoluto. Sigue el mismo "Error defining an external function".
Por cierto, los errores de arriba aparecieron como mensajes estándar de windows, no como un error del GM.
Yo hasta ahora no he tenido problemas con ninguna DLL y lo que dice Alesxander me parece muy importante aunque nunca lo había visto.
Por poner un ejemplo sencillo, yo escribo una dll en CodeBlocks
//Código c++
GMexport double Sumar(double a, double b){
return(double)a+b;
}
Y pones en los Included files de GMS.
Debería funcionar tal y como está, yo lo que hago es en un script definir todas las funciones
global.Sum = external_define("DllExample.dll", "Sumar", dll_cdecl, ty_real, 2, ty_real, ty_real);
Y en otros scripts "repartirlas"
return external_call(global.Sum, 10, 10); o return external_call(global.Sum, argument0, argument1);
Ahora, algo que me pasó, no sé si solo ami fue que si modifico la dll con el proyecto abierto no funcionan las cambios o.o y tengo que eliminarla de los included files y volverla a poner.
Bueno después de esto solo te digo que intentes con otro IDE a ver si funciona.
Consegui que funcionara el Sample que esta dentro del .zip
Despues de trastarlo un poco, se me ocurrio meter todas las dlls que vienen en el .zip y funcionó :D a medias :-\ dentro del object0 en los eventos de "clic mouse" llama un script al cual le da 5 argumentos cuando se supone deberian de ser 4. Por lo que tuve que comentar esos codigos en lo que veo como arreglarlo.
El Sample.gmk lo abri con GM:S, algo más el tipo de dato que debes de usar es Double, este es distinto a float, por lo que al poner float, te seguiria dando error
Cita de: Alesxanderk en Mayo 11, 2016, 05:59:33 AM
Consegui que funcionara el Sample que esta dentro del .zip
Despues de trastarlo un poco, se me ocurrio meter todas las dlls que vienen en el .zip y funcionó :D a medias :-\ dentro del object0 en los eventos de "clic mouse" llama un script al cual le da 5 argumentos cuando se supone deberian de ser 4. Por lo que tuve que comentar esos codigos en lo que veo como arreglarlo.
El Sample.gmk lo abri con GM:S, algo más el tipo de dato que debes de usar es Double, este es distinto a float, por lo que al poner float, te seguiria dando error
Sí sí, eso fue lo primero que pensé, e importé todas las DLL, a excepción del
sample.dll, el cual reemplacé por mi DLL. Además, tuve que modificar uno de los scripts por el mismo (o uno similar, no sé xd) error que te dio. De igual forma no me funcionó.
Disculpa el que no haya contestado antes, la he pasado un poco ocupado :-[
http://gmc.yoyogames.com/index.php?showtopic=317121 - Gm .net Layer (Post sobre la dll).
En el link anterior encontré la información que he mencionado y tambien la dll, no soy muy bueno con el ingles así que no entiendo todo, pero trataré de traducir lo necesario para que puedas crear tus propias dll :D
layer_init() - Llamar antes de usar otras funciones, carga la dll que nos permitira trabajar con nuestra dll.
layer_loaddll (DLL NAME) - Regresa la id de la dll (nuestra, hecha en .net).
layer_createinstance (DLL HANDLE, NAMESPACE . NAME CLASS, ARGCOUNT, args...) - Regresa la id de la "instancia creada con la clase que querramos". (Mostly you have no extra arguments.) El segundo argumento debe de tener la siguiente forma: "Namespace.Classname". El constructor se ejecutara con los argumentos datos (si los hay). Se pueden hcar miltiples instancias de una clase.
layer_function (INSTANCE HANDLE, FUNCTION NAME, RETURNTYPE [ty_real/ty_string],ARGCOUNT, args) - Ejecuta la funcion que deseas, sobrecargas (Overloads) son compatibles.
La dll que tu hagas deben de cumplir los siguientes requerimientos:
* Para recibir/devolver numeros necesitas usar (System.)Double.
* Para recibir/devolver "strings" necesitas usar (System.)String.
* Las funciones a usar y la clase en si deben de ser Publicas(Public) y no Estaticas(Static).
* Solo trabajar con 8 argumentos al mismo tiempo.
* The type of the arguments is automatically detected. // no se bien que dice alli.
Ahora hare algunas aclaraciones que espero puedan ayudarte y ayudar a otros.
Gamemaker trabaja con dll hechas en c y c++ por los estandares que estos siguen, al crear una "función externa" se debe de especificar el "calltype":
* - dll_cdecl - Para C o C++.
* - dll_stdcall - Este es un estandar diferente, desconozco cual es y como usarlo.
Los errores que te saltaban en ventanas de alerta de Windows, es señal de que ibas en buen camino ;D por que cargaba la dll correctamente (la que se usa como mediadora), pero habia un pequeño problema del cual no me percate al momento de leerlos si no hasta despues y es que esta dll fue hecha hace ya tiempo (2007) y no soporta dlls hechas en .NetFrameWork 4.0, debes de usar el 3.0, al menos este me funcionó e hice mi primera dll :love: ahora podre hacer una calculadora con ella :v XD.
Algo más, debido a que no se usar para nada VB, C o C++, utilice C# que lo manejo mejor y conozco que tiene el "namespace" que pide la funcion "layer_createinstance()".
Espero haberte ayudado y solucionado el problema
Bueno, al final logré solucionarlo. Gracias, alesxanderk :'( :D
El problema a la final fue la versión de .NET framework, la cambié a 3.0 y problema resuelto. Aunque antes de hacer eso pasé la extensión a C# xD, voy a probarlo con VB.NET a ver si igual sirve xD