Objective
The previous article on how to render Cocos2d-x 3.6 into the MFC form, here to say how to do the same function in C # WinForm. If you are unfamiliar with MFC's use but are good at C # WinForm, look down.
This article is a copy of the previous article, so some of the operations mentioned in the article need to be found in the previous article ... Bo Master lazy not in this copy paste.
"Core ideas"
In the previous chapter, C # is a managed environment and cannot access the code of the Cocos layer directly in the form of "class. Method ()". We need to build a DLL layer (written in C + +) as an interface to the Cocos layer and let C # control the Cocos layer through the interface.
"Tools Needed"
1. Visual Studio 2013 with C # components installed
2, Cocos2d-x 3.6
3, GLFW (: Point me)
4, CMake (: Point me)
"Action Steps"
1. Create a C # WinForm project
. NET version is optional, use the default and above.
2. Copy the necessary documents
Refer to the previous article
3. Create an empty C + + project
This is the DLL project VS2013 created by the C + + DLL project by default is the Win8.1 platform, do not know what strange things in the inside ... Then manually create a clean DLL project. The project name is self-defined, I use "App"
Once added, set the app project as a dependency of the C # project.
4. Join the Cocos project in the solution
Add Libcocos2d,libbox2d,libspine to the solution and set libcocos2d as the dependency of the app project.
5. Modify the properties of C + + projects
Add the Cocos2dx Two property sheet to the project in the property manager (View-property manager). The property sheet is located in the solution directory \cocos2d\cocos\2d:
General page, set according to the frame:
Debug page, set working directory:
Add-ons to the Include directory:
$ (engineroot) cocos\audio\include
$ (Engineroot) external
$ (engineroot) External\chipmunk\include\chipmunk
$ (engineroot) extensions
.. \classes
..
% (additionalincludedirectories)
$ (_cocos_header_win32_begin)
$ (_cocos_header_win32_end)
In the preprocessor definition, add:
_win32
_windows
Cocos2d_debug=1
_crt_secure_no_warnings
Add to the additional library directory:
$ (_cocos_lib_path_win32_begin)
$ (_cocos_lib_path_win32_end)
Additional dependency joins:
$ (_cocos_lib_win32_begin)
$ (_cocos_lib_win32_end)
Libcocos2d.lib
6, modify the GLFW
Previous article
7, modify the Cocos layer
The previous article, and the method of modifying the Ccfileutils-win32.cpp 59 line:
static void _checkpath () { if (0 = = S_resourcepath.length ()) { char Pathbuffer[max_path] = {0}; WCHAR Wszpath[max_path] = {0}; int nnum = WideCharToMultiByte (CP_ACP, 0, Wszpath, getcurrentdirectory (sizeof (Wszpath), Wszpath), Pathbuffer, MAX_PATH, NULL, NULL); Pathbuffer[nnum] = ' \ \ '; S_resourcepath = Pathbuffer; }}
8. Add code for C + + projects
First add a standard DLL source file Dllmain.cpp ( the name must be this ):
Dllmain.cpp:Defines the entry point for the DLL application. #include <windows.h>bool apientry DllMain (hmodule Hmodule,dword ul_reason_for_call,lpvoid lpreserved) {switch (ul_reason_for_call) {case Dll_process_attach:case Dll_thread_attach:break;case dll_thread_detach:case dll_process_detach://instance'll be deleted automaticallybreak ;} return TRUE;}
Then add the source code in the Classes folder to the project:
Finally add interface (filename custom, I use API.h and API.cpp), header file:
#pragma once#define DLLEXPORT __declspec (DLLEXPORT) extern "C" {
DLLEXPORT void Initialize (HWND parent); DLLEXPORT void Mainloop (); DLLEXPORT void Destory ();};
Realize:
#include "API.h" #include "cocos2d.h" #include "AppDelegate.h" extern "C" { appdelegate app; DLLEXPORT void Initialize (HWND parent) { cocos2d::glviewimpl::setparent (parent); Cocos2d::application::getinstance ()->run (); } DLLEXPORT void Mainloop () { Auto Director = cocos2d::D irector::getinstance (); Director->mainloop (); Director->getopenglview ()->pollevents (); } DLLEXPORT void Destory () { Auto Director = cocos2d::D irector::getinstance (); Director->getopenglview ()->release (); Director->end (); Director->mainloop (); }}
You can then add more functions to the interface based on your requirements.
⑨, modifying the properties of a C # project
To set the output path:
Set up the working directory and enable native code debugging (you can debug the C + + layer after the hook):
10. Add code for C # projects
To add a class that calls DLL code, the name I use is called Nativeinterface:
Using system;using system.runtime.interopservices;namespace cocos2dxcsharp{ class Nativeinterface { Const string dll_name = "App.dll"; [DllImport (dll_name, callingconvention = callingconvention.cdecl)] public static extern void Initialize (int parent); [DllImport (dll_name, callingconvention = callingconvention.cdecl)] public static extern void Mainloop (); [DllImport (dll_name, callingconvention = callingconvention.cdecl)] public static extern void Destory ();} }
In the Form editor, add the load and formclosing two event response methods to the form, and then drag a panel control and a timer control onto the form. The interval value of the timer control is set to 10, and the response method of the Tick event is added.
Then complete the method:
private void Form1_Load (object sender, EventArgs e) { this.timer1.Start (); Nativeinterface.initialize (This.panel1.Handle.ToInt32 ());} private void Form1_formclosing (object sender, FormClosingEventArgs e) { this.timer1.Stop (); Nativeinterface.destory ();} private void Timer1_Tick (object sender, EventArgs e) { nativeinterface.mainloop ();}
11, run up
If the compilation does not go wrong, it will look like this:
"String Pass Processing"
Normal data types (Int,float These) can be passed directly as parameters or return values. Although the string types in C # and the const char* types in C + + are also corresponding, during debugging, you will get an error if you do not process.
Because the managed stack of C # and the DLL stack of C + + do not belong to the same block of memory when debugging, it is like you are holding the address of "Temple of God" in Chengdu, which is a variety of electronic components found in Shanghai is a variety of snacks.
Here's a blog post about how the parameters are passed, and I've probably tidied up a bit:
1. String as parameter
C + +: parameter is char*
C #: Parameter is string, decorated with [MarshalAs (UNMANAGEDTYPE.LPSTR)]
[DllImport ("A.dll"]static extern void Function ([MarshalAs (UNMANAGEDTYPE.LPSTR)]string val);
2. String as return value
C + +: return value is char*
C #: The return value is string, decorated with [Return:marshalas (UNMANAGEDTYPE.LPSTR)])
[DllImport ("A.dll"][return:marshalas (unmanagedtype.lpstr)]static extern string Function ();
3, string as input and output parameters
C + +: parameter is char*
C #: Parameter is byte[] (that blog post mentioned with StringBuilder I can't pass, puzzled)
[DllImport ("A.dll"]static extern void Function (byte[] intoutval);
If you want to pass wide characters, you can use UNMANAGEDTYPE.LPWSTR.
"Cont" forcibly renders cocos2d-x in C # WinForm 3.6