mat.hpp(部分)
#ifdef PATTERNRECOGNITIONTOCLONEDLL_EXPORTS
#define PATTERNRECOGNITION_API __declspec(dllexport)
#else
#define PATTERNRECOGNITION_API __declspec(dllimport)
#endif
extern "C" {
const string pluginFolderPath = "./Assets/Plugin/";
PATTERNRECOGNITION_API cv::Mat* mat_new();
PATTERNRECOGNITION_API cv::Mat* mat_loadPath(const char* path);
}
mat.cpp(部分)
cv::Mat* mat_new() // This works
{
return new cv::Mat();
}
cv::Mat* mat_loadPath(const char* path) // This doesn't
{
Mat* matPtr = new cv::Mat(); // Create an empty Mat
*matPtr = cv::imread(pluginFolderPath + string(path), cv::IMREAD_COLOR); // read the image into the Mat
return matPtr;
}
C#
Mat.cs(部分)
class Mat : HandleCppPtr
{
public Mat(string path) : base(mat_loadPath(path))
{
}
public Mat() : base(mat_new())
{
}
}
HandleCppPtr.cs(部分)
public enum DeleteResponsibility
{
True,
False
}
public abstract class HandleCppPtr
{
public HandleCppPtr(IntPtr cppPtr, DeleteResponsibility deleteResponsibility = DeleteResponsibility.True)
{
CppPtr = cppPtr;
this.deleteResponsibility = deleteResponsibility;
}
~HandleCppPtr()
{
if(this.deleteResponsibility == DeleteResponsibility.True)
{
Debug.Log("[C# ]Deleting HandleCppPtr object -> " + this.ToString());
DeleteCppPtr();
}
else
{
Debug.Log("[C# ] NOT Deleting HandleCppPtr object because deleteResp is False -> " + this.ToString());
}
}
public IntPtr CppPtr
{
get { return handle.Handle; }
set { handle = new HandleRef(this, value); }
}
public DeleteResponsibility deleteResponsibility;
HandleRef handle;
protected abstract void DeleteCppPtr();
}
void Update()
{
string testImagePath = "TestMatImage.png";
if (Input.GetKeyDown(KeyCode.P))
{
Debug.Log("[C# ] Loading Image by Path = " + testImagePath);
Mat mat = new Mat(testImagePath);
Debug.Log(mat.ToString());
}
}
它崩溃了,我收到以下错误:Microsoft Visual C++ 运行时库
运行时错误!程序:
此应用程序已请求运行时以异常方式终止。请联系应用程序的支持团队了解更多信息。
( https://i.stack.imgur.com/LN0Xb.png )
cv::Mat* mat_loadPath(const char* path)
{
string message = "[C++] Loading mat by Path -> " + pluginFolderPath + string(path);
DebugLog(message.c_str()); // Custom function that send debug message to Unity
// PRINT : [C++] Loading mat by Path -> ./Assets/Plugin/TestMatImage.png
Mat* matPtr = new cv::Mat(); // Create an empty Mat
message = "[C++] Mat Not Loaded -> at " + std::to_string((int)matPtr) + " (" + std::to_string(matPtr->rows) + "," + std::to_string(matPtr->cols) + ") ";
DebugLog(message.c_str());
// PRINT: [C++] Mat Not Loaded -> at -1895966160 (0,0)
*matPtr = cv::imread(pluginFolderPath + string(path), cv::IMREAD_COLOR); // read the image into the Mat
message = "[C++] Mat Loaded -> at "+ std::to_string((int)matPtr) +" (" + std::to_string(matPtr->rows) + "," + std::to_string(matPtr->cols) + ") " + std::to_string(matPtr->at<Vec3b>(0, 0).val[1]);
DebugLog(message.c_str());
// PRINT: [C++] Mat Loaded -> at -1895966160 (10,10) 231
return new cv::Mat(); // If this is replaced by matPtr, the call of the
}
我找到了崩溃的原因,后来我想获得我作为错误类型的值(Vecd 而不是正确的 Vec3b)的值。此外,我在测试时也没有使用“new cv::Mat()”,这会导致 Mat 被 C++ 丢弃(以及指向随机内容的 C#)。
对于任何想要做类似事情的人,这里是我的代码(即使它的灵感来自 NormandErwan 的 ArucoUnity/ArucoUnityPlugin)。
#ifdef PATTERNRECOGNITIONTOCLONEDLL_EXPORTS
#define PATTERNRECOGNITION_API __declspec(dllexport)
#else
#define PATTERNRECOGNITION_API __declspec(dllimport)
#endif
.hpp文件
#include <opencv2/core.hpp>
#include "PatternRecognition.hpp"
using namespace CloneToTangible;
extern "C" {
const string pluginFolderPath = "./Assets/Plugin/";
PATTERNRECOGNITION_API cv::Mat* mat_new();
PATTERNRECOGNITION_API cv::Mat* mat_loadPath(const char* path);
PATTERNRECOGNITION_API void mat_delete(cv::Mat* matPtr);
PATTERNRECOGNITION_API Vec3b* mat_at(cv::Mat* mat, uint posX, uint posY);
PATTERNRECOGNITION_API int mat_rows(cv::Mat* mat);
PATTERNRECOGNITION_API int mat_cols(cv::Mat* mat);
PATTERNRECOGNITION_API int mat_type(cv::Mat* mat);
}
垫子文件
#include "pch.h"
#include "mat.hpp"
#include <opencv2\imgcodecs.hpp>
cv::Mat* mat_new()
{
Mat* matPtr = new cv::Mat();
//DebugLog(("[C++] Mat Loaded -> at " + std::to_string((int)matPtr) + " (" + std::to_string(matPtr->rows) + "," + std::to_string(matPtr->cols) + ") " + std::to_string(matPtr->at<Vec3b>(0, 0).val[1])).c_str());
return matPtr;
}
cv::Mat* mat_loadPath(const char* path)
{
//DebugLog(("[C++] Loading mat by Path -> " + pluginFolderPath + string(path)).c_str());
Mat* matPtr = new cv::Mat();
*matPtr = cv::imread(pluginFolderPath + string(path), cv::IMREAD_COLOR);
//DebugLog(("[C++] Mat Loaded -> at " + std::to_string((int)matPtr) + " (" + std::to_string(matPtr->rows) + "," + std::to_string(matPtr->cols) + ") " + std::to_string(matPtr->at<Vec3b>(0, 0).val[1])).c_str());
return matPtr;
}
void mat_delete(cv::Mat* matPtr)
{
delete matPtr;
}
Vec3b* mat_at(cv::Mat* mat, uint posX, uint posY)
{
return new Vec3b(mat->at<Vec3b>(posX,posY));
}
int mat_rows(cv::Mat* mat)
{
//DebugLog(("Returning rows for " + std::to_string((int)&mat) + " which is " + std::to_string(mat->rows)).c_str());
return mat->rows;
}
int mat_cols(cv::Mat* mat)
{
//DebugLog(("Returning cols for " + std::to_string((int)&mat) + " which is " + std::to_string(mat->cols)).c_str());
return mat->cols;
}
int mat_type(cv::Mat* mat)
{
return mat->type();
}
vec3b.hpp
#include <opencv2/core.hpp>
#include "PatternRecognition.hpp"
extern "C" {
PATTERNRECOGNITION_API cv::Vec3b* cv_Vec3b_new(unsigned char v0, unsigned char v1, unsigned char v2);
PATTERNRECOGNITION_API void cv_Vec3b_delete(cv::Vec3b* vec3dPtr);
PATTERNRECOGNITION_API unsigned char cv_Vec3b_get(cv::Vec3b* vec3dPtr, int i);
PATTERNRECOGNITION_API void cv_Vec3b_set(cv::Vec3b* vec3dPtr, int i, unsigned char value);
PATTERNRECOGNITION_API void cv_Vec3b_setAll(cv::Vec3b* vec3dPtr, unsigned char v0, unsigned char v1, unsigned char v2);;
}
vec3b.cpp
#include "pch.h"
#include "vec3b.hpp"
cv::Vec3b* cv_Vec3b_new(unsigned char v0, unsigned char v1, unsigned char v2)
{
return new cv::Vec3b(v0, v1, v2);
}
void cv_Vec3b_delete(cv::Vec3b* vec3bPtr)
{
int n = (*vec3bPtr)[0];
delete vec3bPtr;
}
unsigned char cv_Vec3b_get(cv::Vec3b* vec3bPtr, int i)
{
unsigned char value = 0;
try {
value = (*vec3bPtr)[i];
}
catch (const cv::Exception& e) {
return value;
}
return value;
}
void cv_Vec3b_set(cv::Vec3b* vec3bPtr, int i, unsigned char value)
{
try {
(*vec3bPtr)[i] = value;
}
catch (const cv::Exception& e) {
}
}
void cv_Vec3b_setAll(cv::Vec3b* vec3bPtr, unsigned char v0, unsigned char v1, unsigned char v2)
{
try {
(*vec3bPtr)[0] = v0;
(*vec3bPtr)[1] = v1;
(*vec3bPtr)[2] = v2;
}
catch (const cv::Exception& e) {
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
class Mat : HandleCppPtr
{
public int cols
{
get { return mat_cols(CppPtr); }
}
public int rows
{
get { return mat_rows(CppPtr); }
}
public int type
{
get { return mat_type(CppPtr); }
}
[DllImport("PatternRecognitionToCloneDLL")]
static extern IntPtr mat_new();
[DllImport("PatternRecognitionToCloneDLL")]
public static extern IntPtr mat_loadPath(string path);
[DllImport("PatternRecognitionToCloneDLL")]
static extern void mat_delete(IntPtr matPtr);
[DllImport("PatternRecognitionToCloneDLL")]
static extern IntPtr mat_at(IntPtr matPtr, uint x, uint y);
[DllImport("PatternRecognitionToCloneDLL")]
static extern int mat_cols(IntPtr matPtr);
[DllImport("PatternRecognitionToCloneDLL")]
static extern int mat_rows(IntPtr matPtr);
[DllImport("PatternRecognitionToCloneDLL")]
static extern int mat_type(IntPtr matPtr);
public Mat(string path, DeleteResponsibility deleteResponsibility = DeleteResponsibility.True) : base(mat_loadPath(path), deleteResponsibility)
{
Debug.Log("[C#] Mat Instantiation : Mat(string path) ");
}
public Mat(DeleteResponsibility deleteResponsibility = DeleteResponsibility.True) : base(mat_new(), deleteResponsibility)
{
Debug.Log("[C#] Mat Instantiation : Mat() ");
}
public Mat(IntPtr cppPtr, DeleteResponsibility deleteResponsibility = DeleteResponsibility.True) : base(cppPtr, deleteResponsibility)
{
}
public Vec3b At(uint x, uint y)
{
if (x < rows && y < cols)
return new Vec3b(mat_at(this.CppPtr, x, y));
else
return new Vec3b();
}
protected override void DeleteCppPtr()
{
//Debug.Log("[C#] Mat Destruction : DeleteCppPtr(), before mat_delete() call ");
mat_delete(this.CppPtr);
//Debug.Log("[C#] Mat Destruction : DeleteCppPtr(), after mat_delete() call ");
}
public override string ToString()
{
string message = "Mat->";
int rows = mat_rows(this.CppPtr);
Debug.Log("[C#] Mat has " + rows + " rows");
int cols = mat_cols(this.CppPtr);
Debug.Log("[C#] Mat has " + cols + " cols");
for (uint x = 0; x < rows; x++)
{
message += "\n {";
for (uint y = 0; y < cols; y++)
{
message += At(x, y).ToString();
}
message += "}";
}
return message;
}
}
Vec3b.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
public class Vec3b : HandleCppPtr
{
[DllImport("PatternRecognitionToCloneDLL")]
static extern IntPtr cv_Vec3b_new(byte v0, byte v1, byte v2);
[DllImport("PatternRecognitionToCloneDLL")]
static extern void cv_Vec3b_delete(IntPtr vec3bPtr);
[DllImport("PatternRecognitionToCloneDLL")]
static extern byte cv_Vec3b_get(IntPtr vec3bPtr, int i);
[DllImport("PatternRecognitionToCloneDLL")]
static extern void cv_Vec3b_set(IntPtr vec3bPtr, int i, byte value);
[DllImport("PatternRecognitionToCloneDLL")]
static extern void cv_Vec3b_setAll(IntPtr vec3bPtr, byte v0, byte v1, byte v2);
public Vec3b(byte v0 = 0, byte v1 = 0, byte v2 = 0) : base(cv_Vec3b_new(v0, v1, v2))
{
}
public Vec3b(IntPtr cppPtr) : base(cppPtr)
{
}
protected override void DeleteCppPtr()
{
cv_Vec3b_delete(this.CppPtr);
}
public int Get(int i)
{
return cv_Vec3b_get(this.CppPtr, i);
}
public void Set(int i, byte value)
{
cv_Vec3b_set(this.CppPtr, i, value);
}
public void Set(byte v0, byte v1, byte v2)
{
cv_Vec3b_setAll(this.CppPtr, v0, v1, v2);
}
public override string ToString()
{
string message = "Vec3b->";
message += "(" + Get(0) + "," + Get(1) + "," + Get(2) + ")";
return message;
}
}
处理CppPtr.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
public enum DeleteResponsibility
{
True,
False
}
public abstract class HandleCppPtr
{
public HandleCppPtr(IntPtr cppPtr, DeleteResponsibility deleteResponsibility = DeleteResponsibility.True)
{
CppPtr = cppPtr;
this.deleteResponsibility = deleteResponsibility;
}
~HandleCppPtr()
{
if(this.deleteResponsibility == DeleteResponsibility.True)
{
//Debug.Log("[C# ]Deleting HandleCppPtr object -> " + this.ToString());
DeleteCppPtr();
}
else
{
//Debug.Log("[C# ] NOT Deleting HandleCppPtr object because deleteResp is False -> " + this.ToString());
}
}
public IntPtr CppPtr
{
get { return handle.Handle; }
set { handle = new HandleRef(this, value); }
}
public DeleteResponsibility deleteResponsibility;
HandleRef handle;
protected abstract void DeleteCppPtr();
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句