我试图将字节数组从我的非托管c dll返回到c#unity.
非常感谢您抽出宝贵的时间来帮助><我在团结中对DLL非常陌生,所以我非常困惑2种语言甚至可以合作.
CPP
问题出在这里,我已经完成了我的计算,但我很难找到一种方法将数据格式返回给c#.
目前,字节数组包含颜色代码,例如RGBA(223,124,23,255,212,143,234,255),它重复
#include "WebcamDLL.h"
#include <vector>
extern "C" {
int adjustBrightnesss(unsigned char* bytes, int sizeOfArray)
{
std::vector<int> myvector;
int alphaP = 0;
for (int i = 0; i < sizeOfArray; i++) {
switch (alphaP) {
case 0:
case 1:
case 2:
myvector[i] = bytes[i] / 2;
alphaP++;
break;
case 3:
alphaP = 0;
break;
}
}
return bytes;
}
}
头文件
#ifdef TESTFUNCDLL_EXPORT
#define TESTFUNCDLL_API __declspec(dllexport)
#else
#define TESTFUNCDLL_API __declspec(dllimport)
#endif
extern "C" {
TESTFUNCDLL_API int adjustBrightnesss(unsigned char* bytes, int sizeOfArray);
}
C#文件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices; // Needed for custom DLL
using System;
public class WebcamManager : MonoBehaviour
{
private RawImage ri; // Gets the RawImage component from script parent
private WebCamTexture wct; // Object to hold the WebCamTexture add-on
private AspectRatioFitter arf; // Ensures RawImage object has same scaling as Webcam
private Color32[] pixels; // Keeps the pixels from webcamtexture
Texture2D tex; // A placeholder for the texture2D
[DllImport("WebcamBrightness", EntryPoint = "adjustBrightness")]
public static extern int adjustBrightness(byte bytes, int b);
void Start()
{
newBrightness = 1; // Default 1, if 0 will make image go super bright
arf = GetComponent<AspectRatioFitter>(); // Gets the component AspectRatioFitter in script parent
ri = GetComponent<RawImage>(); // Gets the component RawImage in script parent
wct = new WebCamTexture(Screen.width, Screen.height); // Creates a new WebCamTexture in wct with the width and height of the current screen
wct.Play(); // plays webcam
//adjustBrightness(wct.GetPixels32());
}
// Update is called once per frame
void Update()
{
float videoRatio = (float)wct.width / (float)wct.height; // Ensures that the scaling is the same as the webcam
arf.aspectRatio = videoRatio; // applies webcam scaling to rawimage
tex = new Texture2D(wct.width, wct.height, TextureFormat.ARGB32, false); // pass texture2D tex the information of webcamtexture height, width, ARGB32 (32 bit with alpha) and no mipmaps
pixels = wct.GetPixels32();
// After getting the bytes, I wanna save it back to color32 or atleast an array format.
tex.SetPixels32(pixels);
tex.Apply();
// Sets texture of rawimage from canvas to be web camera view
ri.texture = tex;
}
}
编写CPP文件
#include "WebcamDLL.h"
#include <vector>
extern "C" {
unsigned char* adjustBrightness(unsigned char* bytes, int sizeOfArray)
{
int alphaP = 0;
for (int i = 0; i < sizeOfArray; i++) {
switch (alphaP) {
case 0:
case 1:
case 2:
bytes[i] = bytes[i] / 2;
alphaP++;
break;
case 3:
alphaP = 0;
break;
}
}
return bytes;
}
int freeMem(unsigned char* arrayPtr) {
delete[] arrayPtr;
return 0;
}
}
编辑的头文件
#ifdef TESTFUNCDLL_EXPORT
#define TESTFUNCDLL_API __declspec(dllexport)
#else
#define TESTFUNCDLL_API __declspec(dllimport)
#endif
extern "C" {
TESTFUNCDLL_API unsigned char* adjustBrightness(unsigned char* bytes, int sizeOfArray);
TESTFUNCDLL_API int freeMem(unsigned char* arrayPtr);
}
编写C#文件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices; // Needed for custom DLL
using System;
public class WebcamManager : MonoBehaviour
{
private RawImage ri; // Gets the RawImage component from script parent
private WebCamTexture wct; // Object to hold the WebCamTexture add-on
private AspectRatioFitter arf; // Ensures RawImage object has same scaling as Webcam
private Color32[] pixels; // Keeps the pixels from webcamtexture
Texture2D tex; // A placeholder for the texture2D
public RawImage ri2;
float timer;
[DllImport("WebcamBrightness", EntryPoint = "adjustBrightness", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr adjustBrightness(byte[] bytes, int b);
[DllImport("WebcamBrightness", EntryPoint = "freeMem", CallingConvention = CallingConvention.Cdecl)]
public static extern int freeMem(IntPtr ptr);
[SerializeField]
int newBrightness;
void Start()
{
newBrightness = 1; // Default 1, if 0 will make image go super bright
arf = GetComponent<AspectRatioFitter>(); // Gets the component AspectRatioFitter in script parent
ri = GetComponent<RawImage>(); // Gets the component RawImage in script parent
wct = new WebCamTexture(Screen.width, Screen.height); // Creates a new WebCamTexture in wct with the width and height of the current screen
wct.Play(); // plays webcam
float videoRatio = (float)wct.width / (float)wct.height; // Ensures that the scaling is the same as the webcam
arf.aspectRatio = videoRatio; // applies webcam scaling to rawimage
tex = new Texture2D(wct.width, wct.height, TextureFormat.ARGB32, false); // pass texture2D tex the information of webcamtexture height, width, ARGB32 (32 bit with alpha) and no mipmaps
}
// Update is called once per frame
void Update()
{
//timer += Time.deltaTime;
pixels = wct.GetPixels32();
IntPtr returnedPtr = adjustBrightness(Color32ArrayToByteArray(pixels), Color32ArrayToByteArray(pixels).Length);
byte[] returnedResult = new byte[Color32ArrayToByteArray(pixels).Length];
Marshal.Copy(returnedPtr, returnedResult, 0, Color32ArrayToByteArray(pixels).Length);
freeMem(returnedPtr);
Debug.Log(returnedResult[0]);
tex.SetPixels32(pixels);
ri.texture = tex;
tex.Apply();
// Sets texture of rawimage from canvas to be web camera view
}
public void AdjustBrightness(float b)
{
newBrightness = (int)b;
}
private static byte[] Color32ArrayToByteArray(Color32[] colors)
{
if (colors == null || colors.Length == 0)
return null;
int lengthOfColor32 = Marshal.SizeOf(typeof(Color32));
int length = lengthOfColor32 * colors.Length;
byte[] bytes = new byte[length];
GCHandle handle = default(GCHandle);
try
{
handle = GCHandle.Alloc(colors, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
Marshal.Copy(ptr, bytes, 0, length);
}
finally
{
if (handle != default(GCHandle))
handle.Free();
}
return bytes;
}
}
解决方法:
有很多方法可以从C#返回字节数组,下面是其中之一.内存分配和解除分配都在C中完成.您必须调用该函数以从C#中释放内存.我使示例非常简单,以便您可以轻松地将其集成到当前代码中.
IntPtr是这个答案的关键.
C :
char* getByteArray()
{
//Create your array(Allocate memory)
char * arrayTest = new char[2];
//Do something to the Array
arrayTest[0]=3;
arrayTest[1]=5;
//Return it
return arrayTest;
}
int freeMem(char* arrayPtr){
delete[] arrayPtr;
return 0;
}
C#:
[DllImport("Test.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr getByteArray();
[DllImport("Test.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int freeMem(IntPtr ptr);
//Test
void Start() {
//Call and return the pointer
IntPtr returnedPtr = getIntArray();
//Create new Variable to Store the result
byte[] returnedResult = new byte[2];
//Copy from result pointer to the C# variable
Marshal.Copy(returnedPtr, returnedResult, 0, 2);
//Free native memory
freeMem(returnedPtr);
//The returned value is saved in the returnedResult variable
byte val1 = returnedResult[0];
byte val2 = returnedResult[1];
}
原文地址:https://codeday.me/bug/20190929/1830867.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。