How to debug dll (Unity)? - unity3d

I have a Unity project that use dll.
This is an example I try to use : https://www.youtube.com/watch?v=C6V1f86x058
In order to make it work I :
created C# script
Added dll under Assets folder
My script is
using System;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.Rendering;
public class TestScript : MonoBehaviour
{
//the name of the DLL you want to load stuff from
private const string pluginName = "AndroidNativeLib";
//native interface
[DllImport(pluginName)]
private static extern IntPtr getEventFunction();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DebugDelegate(string str);
static void CallBackFunction(string str) { Debug.Log(str); }
[DllImport(pluginName)]
public static extern void SetDebugFunction(IntPtr fp);
private CommandBuffer cmd;
// Start is called before the first frame update
void Start()
{
DebugDelegate callback_delegate = new DebugDelegate(CallBackFunction);
// Convert callback_delegate into a function pointer that can be
// used in unmanaged code.
IntPtr intptr_delegate =
Marshal.GetFunctionPointerForDelegate(callback_delegate);
// Call the API passing along the function pointer.
SetDebugFunction(intptr_delegate);
//crating the command buffer and attaching it to camera
cmd = new CommandBuffer();
cmd.name = pluginName;
var camera = Camera.main;
camera.AddCommandBuffer(CameraEvent.AfterGBuffer, cmd);
}
// Update is called once per frame
void Update()
{
cmd.IssuePluginEvent(getEventFunction(), 0);
}
}
And my dll is :
#include "stdafx.h"
#include "IUnityGraphics.h"
//make sure this appears before IUnityGraphicsD3D11
#include "d3d11.h"
#include "IUnityGraphicsD3D11.h"
// debug event
typedef void(*FuncPtr)(const char *);
FuncPtr Debug;
namespace globals {
ID3D11Device *device = nullptr;
ID3D11DeviceContext *context = nullptr;
} // namespace globals
extern "C" {
UNITY_INTERFACE_EXPORT void SetDebugFunction(FuncPtr fp) { Debug = fp; }
// Plugin function to handle a specific rendering event
static void UNITY_INTERFACE_API UNITY_INTERFACE_API OnRenderEvent(int eventID) {
Debug("Hello world");
}
// Unity plugin load event
void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
UnityPluginLoad(IUnityInterfaces *unityInterfaces) {
auto s_UnityInterfaces = unityInterfaces;
IUnityGraphicsD3D11 *d3d11 = unityInterfaces->Get<IUnityGraphicsD3D11>();
globals::device = d3d11->GetDevice();
globals::device->GetImmediateContext(&globals::context);
}
// Unity plugin unload event
void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() {}
// Freely defined function to pass a callback to plugin-specific scripts
UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
getEventFunction() {
return OnRenderEvent;
}
}
When I run this example I don't see any outputs and it does not looks like it work. So, I tried to debug it. I can get debug point in C# script, but if I try to reach one from dll code, noting happens.
So, question is - how to debug dll code?

Does this help: https://forum.unity.com/threads/how-to-build-and-debug-external-dlls.161685/
create a .csproj file that uses wildcards to find all source code
add this C# project to a Visual Studio solution
use an MSBuild post-build target to convert Visual Studio's PDB symbols to Mono's MDB format
debug with MonoDevelop from Unity, as normal
source code should -not- be in the Assets folder, but the generated DLL should be

Related

ESP8266 Scheduler. Tasks in separate files arduino IDE

I want to create simple weather station with esp8266 but with scheduler to updating data and GUI more simultaneously. I've downloaded scheduler from here but there is information:
Tasks must be declared globally on the stack (not a pointer). Failure to do so will crash your device
Does that mean that I have to write all task classes in *.ino file? Can I save them in separate files and call to sketch file? How to do that? I've tried few times but the code won't compile.
Simpliest example of sketch:
#include <Scheduler.h>
#include <Arduino.h>
class SimpleTask : public Task {
protected:
void setup() {
Serial.println("Setup func");
}
void loop() {
Serial.println("Loop func");
delay(600);
}
} simple_task;
void setup() {
Serial.begin(115200);
Scheduler.start(&simple_task);
Scheduler.begin();
}
void loop() { }
Tasks must be declared globally on the stack (not a pointer).
I think strictly this means that Tasks must not be created on the heap and need to be global, static objects.
This can be done by creating the object in a separate file and declaring the object using the extern keyword.
e.g. an example mysimpletask.h:
#ifndef __MySIMPLETASK_H__
#define __MySIMPLETASK_H__
#include <Scheduler.h>
class MySimpleTask : public Task {
protected:
void setup();
void loop();
};
extern MySimpleTask my_simple_task;
#endif
The implementation in mysimpletask.cpp:
#include "mysimpletask.h"
void MySimpleTask::setup() {
Serial.println("Setup func");
}
void MySimpleTask::loop() {
Serial.println("Loop func");
delay(600);
}
MySimpleTask my_simple_task;
And the sketch:
#include <Scheduler.h>
#include <Arduino.h>
#include "mysimpletask.h"
void setup() {
Serial.begin(115200);
Scheduler.start(&my_simple_task);
Scheduler.begin();
}
void loop() { }

How can I force an orientation per scene in Unity3D

Unity3D has a Screen class with an orientation property that allows you to force orientation in code, which lets you have different scenes with different orientations (useful in mini-games).
Setting this works fine for Android but crashes on iOS. What is the fix?
The problem is the file UnityViewControllerBaseiOS.mm that gets generated during the build for iOS has an assert in it which inadvertently prevents this property from being used. It is possible to create a post-build class that runs after the iOS build files have been generated that can alter the generated code before you compile it in XCode.
Just create a C# script named iOSScreenOrientationFix.cs and paste in the following code - adapted from this Unity3D forum post. Note that this file must be placed in a folder named Editor, or in one of its subfolders.
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using System.IO;
namespace Holovis
{
public class iOSScreenOrientationFix : MonoBehaviour
{
#if UNITY_CLOUD_BUILD
// This method is added in the Advanced Features Settings on UCB
// PostBuildProcessor.OnPostprocessBuildiOS
public static void OnPostprocessBuildiOS (string exportPath)
{
Debug.Log("OnPostprocessBuildiOS");
ProcessPostBuild(BuildTarget.iPhone,exportPath);
}
#endif
[PostProcessBuild]
public static void OnPostprocessBuild(BuildTarget buildTarget, string path)
{
#if !UNITY_CLOUD_BUILD
ProcessPostBuild(buildTarget, path);
#endif
}
private static void ProcessPostBuild(BuildTarget buildTarget, string path)
{
if (buildTarget == BuildTarget.iOS)
{
#if !UNITY_CLOUD_BUILD
Debug.Log("Patching iOS to allow setting orientation");
#endif
string filePath = Path.Combine(path, "Classes");
filePath = Path.Combine(filePath, "UI");
filePath = Path.Combine(filePath, "UnityViewControllerBaseiOS.mm");
Debug.Log("File Path for View Controller Class: " + filePath);
string classFile = File.ReadAllText(filePath);
string newClassFile = classFile.Replace("NSAssert(UnityShouldAutorotate()", "//NSAssert(UnityShouldAutorotate()");
File.WriteAllText(filePath, newClassFile);
}
}
}
}
You can set it in a scene by attaching the following MonoBehaviour to a game object
using UnityEngine;
namespace Holovis
{
public class SetDeviceOrientation : MonoBehaviour
{
public ScreenOrientation orientation = ScreenOrientation.AutoRotation;
void Awake()
{
Screen.orientation = orientation;
}
}
}
NOTE: Setting Screen.orientation has no effect when running on desktop, in the Unity editor, or when testing using Unity Remote.

Unmanaged method member being used as a delegate in managed class

I have a project where I am expanding existing native C++ compatible code functionality for a customer-facing library by integrating a driver from a managed DLL, which seems like the opposite direction for most marshaling questions. Since there can be multiple devices using this one driver, each device needs to be its own object, with its own callback methods. This integration will take the form of a native wrapper DLL that exposes the native class interface to the customer-facing library, which will pass an instance of a member method callback function pointer to the DLL. I need to pass a native method member instance (non-static) as a delegate to the managed wrapper class. The managed wrapper class uses GetDelegateForFunctionPointer, which works to marshal static native pointers to a delegate, but I can't find any information if it works with instances. GetDelegateForFunctionPointer also takes a System::IntPtr argument for the function pointer, but I'm also not sure if System::IntPtr works for instances, and when compiling in VC++2008 I'm being presented an error C3867 for attempting this.
Managed wrapper header:
//somemanagedclass.hpp
#pragma once
using namespace System;
using namespace ExternalManagedLibrary;
namespace SomeNameSpace
{
public ref class SomeManagedClass
{
public:
SomeManagedClass();
~SomeManagedClass();
delegate void CallbackHandler(const wchar_t*, int);
CallbackHandler^ CallbackEvent;
void RegisterCallback(IntPtr callbackEvent);
private:
ExternalManagedClass^ externalManagedClass;
void OnCallback(Object^ sender, ValueEventArgs<String^>^ e);
};
}
Managed wrapper source:
//somemanagedclass.cpp
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace System;
using namespace Runtime::InteropServices;
namespace SomeNameSpace
{
SomeManagedClass::SomeManagedClass()
{
externalManagedClass = gcnew ExternalManagedClass();
externalManagedClass->CallbackEvent += gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
SomeManagedClass::~SomeManagedClass()
{
externalManagedClass->CallbackEvent -= gcnew EventHandler<ValueEventArgs<String^>^>(this, &SomeManagedClass::OnCallback);
}
void SomeManagedClass::OnCallback(Object^ sender, ValueEventArgs<String^>^ e)
{
String^ some_string = String::Copy(e->Value);
cli::pin_ptr<const wchar_t> pinned_string = &PtrToStringChars(some_string)[0];
const wchar_t* p = pinned_string;
CallbackEvent(pinned_string, some_string->Length);
}
void SomeManagedClass::RegisterCallback(IntPtr callbackEvent)
{
CallbackEvent = (CallbackHandler^)(Marshal::GetDelegateForFunctionPointer(callbackEvent, CallbackHandler::typeid));
}
}
Native wrapper interface:
//somenativeinterface.hpp
#ifdef DLL_EXPORT
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif //DLL_EXPORT
typedef void (*NativeCallback)(const unsigned char*, unsigned long);
class IMPORT_EXPORT SomeNativeInterface
{
public:
//class factory
static SomeNativeInterface* Create(void);
static void Destroy(SomeNativeInterface* clInterface);
virtual void CallbackInit(NativeCallback fnNativeCallbackInit);
};
Native wrapper header:
//somenativeclass.hpp
#pragma once
#include "somenativeinterface.hpp"
#include "somemanagedclass.hpp"
#include <vcclr.h>
using namespace SomeNameSpace;
class IMPORT_EXPORT SomeNativeClass : public SomeNativeInterface
{
public:
SomeNativeClass();
~SomeNativeClass();
void CallbackInit(NativeCallback fnNativeCallbackInit); //can this take an instance?
private:
NativeCallback fnNativeCallback;
void OnNativeCallback(const wchar_t* cString, int iSize);
gcroot<SomeManagedClass^> wrapper; //warning C4251
};
Native wrapper source:
//somenativeclass.cpp
#include "somenativeclass.hpp"
#include <vcclr.h>
#include <string.h>
using namespace System;
using namespace Runtime::InteropServices;
SomeNativeInterface* SomeNativeInterface::Create()
{
return ((SomeNativeInterface*) new SomeNativeClass());
}
void SomeNativeInterface::Destroy(SomeNativeInterface* instance)
{
delete instance;
}
SomeNativeClass::SomeNativeClass()
{
wrapper = gcnew SomeManagedClass();
}
SomeNativeClass::OnNativeCallback(const wchar_t* cString, int iSize)
{
std::auto_ptr<char> pcConvertedString(new char[iSize+1]);
size_t iCharsConverted;
if (wcstombs_s(&iCharsConverted, (char*)*pcConvertedString, iSize+1, cString, iSize) == 0)
{
if (iCharsConverted > 0xFFFFFFFF)
iCharsConverted = 0xFFFFFFFF; //truncate
fnNativeCallback((const unsigned char*)*pcConvertedString, (unsigned long)(iCharsConverted));
}
}
SomeNativeClass::CallbackInit(NativeCallback fnNativeCallbackInit)
{
fnNativeCallback = fnNativeCallbackInit;
wrapper->RegisterCallback(System::IntPtr(this->OnNativeCallback)); //error C3867
}

char* as function return value with Unity plugin

I would like to use char* as a return value (like it is done in Unity's example plugin) but I get some invalid markings (效汬o) instead of simple "Hello". Any ideas what could be wrong?
DLL:
extern "C"
{
const __declspec(dllexport) char* PrintHello()
{
return "Hello";
}
}
Unity:
public class audiotest : MonoBehaviour
{
[DllImport("ASimplePlugin")]
private static extern IntPtr PrintHello();
void Start ()
{
Debug.Log(Marshal.PtrToStringAuto(PrintHello()));
}
}
Unity's example plugin can be found http://docs.unity3d.com/Documentation/Images/manual/SimplestPluginExample-4.0.zip
I am using Unity 4.2.1f4 and Visual Studio 2010
Use PtrToStringAnsi instead of PtrToStringAuto.
Your DLL is returning an ANSI string, but PtrToStringAuto expects Unicode on anything except Windows 98.

Is it possible to point a Typedef function pointer to a class member?

I am working with an executable that includes a DLL. For my testcase, I combined the code into a single executable. I am working with Visual Studio 2008 and Boost 1.43. I've tried researching this, but haven't found any clear answer. Thanks for the help.
In my main.h:
#include <string>
//These are normally defined in a seperate DLL
typedef std::string Typedef_func(const std::string & title);
void Register_My_Typedef(Typedef_func*);
//-------------------------------------------
class myClass
{
public:
std::string func_one(const std::string & title);
Typedef_func _test;
void run();
};
In my main.cpp:
#include "main.h"
#include <boost/bind.hpp>
std::string workingFunc(const std::string & title)
{
return "";
}
int main(int argc, char* argv[])
{
myclass* example;
example->run();
Register_My_Typedef(&workingFunc);//This works.
return 0;
}
void myClass::run()
{
//I want to point a Typedef_func* in a DLL to call myclass::func_one
Typedef_func* tf = boost::bind(&myClass::func_one, this, "test"); //This does not.
Register_My_Typedef(tf);
}
std::string myClass::funcOne(const std::string & title)
{
return "";
}
void Register_My_Typedef(Typedef_func* passedIn)
{
//Points the pointer in the DLL to passedIn
}
The DLL logic works fine when Register_My_Typedef is called on a function not in a class, but is it possible to call it from within a class? When I try to compile this code it returns:
When I try and compile in Windows XP with VS2008 I get:
Error C2440: 'initializing' : cannot convert from
'boost::_bi::bind_t' to 'Typedef_func (__cdecl *)' with
[
R=std::string,
F=boost::_mfi::mf1,
L=boost::_bi::list2,boost::_bi::value>
]
No user-defined-conversion operator available that can perform this
conversion, or the operator cannot be called.
The Answer is Typedef itself is class member for a static member function & behave differently to non-static however works best reading rather class function of user defined class main.