我试图将字节数组从我的非托管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;
}
}
EDITTED HEADER FILE
#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;
}
}
答案 0 :(得分:5)
有许多方法可以从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];
}
答案 1 :(得分:0)
你可以向函数传递一个额外的参数,让我们说另一个字节数组,然后在adjustBrightnesss函数中用该数组替换myvector。据我所知,您将获得具有修改值的数组