У меня есть C ++ библиотека , которую я изменяю и компилирую как .dll для использования в C# приложении. Библиотека состоит из одной библиотеки заголовков, которая теперь выглядит следующим образом:
#include <array>
#include <vector>
#include <cmath>
typedef std::array<double, 2> Point;
std::vector<Point> samples;
extern "C" {
__declspec(dllexport) void __cdecl initSamplers();
__declspec(dllexport) unsigned int __cdecl ldbnBNOT(const unsigned int nbPts);
__declspec(dllexport) Point* __cdecl getPointAt(unsigned int i);
__declspec(dllexport) void __cdecl releasePointAt(double* pArray);
}
unsigned mirror[256];
inline double phi(const unsigned &i){
const unsigned ONE = 0x1000000;
const double scl = 1.0 / ONE;
return scl * (
mirror[(i >> 16) & 255] +
(mirror[(i >> 8) & 255] << 8) +
(mirror[i & 255] << 16)
);
}
extern void __cdecl initSamplers(){
for (unsigned i = 0; i < 256; i++) {
mirror[i] = (i >> 7) + ((i >> 5) & 2) + ((i >> 3) & 4) + ((i >> 1) & 8) + ((i << 1) & 16) + ((i << 3) & 32) + ((i << 5) & 64) + ((i << 7) & 128);
}
}
extern Point* __cdecl getPointAt(unsigned int i){
if (samples.size() > 0) return &samples.at(i);
else return nullptr;
}
extern void __cdecl releasePointAt(double* pArray){
delete[] pArray;
}
extern unsigned int __cdecl ldbnBNOT(const unsigned int nbPts){
samples.clear();
auto n = std::floor(std::sqrt((double)nbPts));
Point p;
double inv = 1.0 / n;
unsigned mask = 128 - 1;
unsigned shift = std::log2(128);
for (unsigned Y = 0; Y < n; Y++) {
for (unsigned X = 0; X < n; X++) {
unsigned index = ((Y & mask) << shift) + (X & mask);
double u = phi((Y & 0xfffffff0) + (lutLDBN_BNOT[index] & 0xf));
double v = phi((X & 0xfffffff0) + (lutLDBN_BNOT[index] >> 4));
p[0] = inv * (X + u);
p[1] = inv * (Y + v);
samples.push_back(p);
}
}
return samples.size();
}
Затем внутри моего приложения C# я импортирую свою DLL и затем вызываю различные функции. Я выгляжу примерно так:
namespace RandomPointGenerator
{
internal static class UnsafeNativeMethods
{
const string _dllLocation = "LowDiscBlueNoise.dll";
[DllImport(_dllLocation)]
public static extern void initSamplers();
[DllImport(_dllLocation)]
public static extern int ldbnBNOT(int samples);
[DllImport(_dllLocation)]
public static extern IntPtr getPointAt(int i);
[DllImport(_dllLocation)]
public static extern void releasePointAt(IntPtr ptr);
}
public class Populate2D
{
public Populate2D()
: base("Name", "Nickname", "Description")
{
}
public static void InitSamplers(){
UnsafeNativeMethods.initSamplers();
}
public static int GeneratePts(int samples){
return UnsafeNativeMethods.ldbnBNOT(samples);
}
public static Point3d getPointAt(int i){
IntPtr ptr = UnsafeNativeMethods.getPointAt(i);
double[] pt = new double[2];
Marshal.Copy(ptr, pt, 0, 2);
if (pt.Length < 0) pt = new double[2] { 0.0, 0.0 };
//releasePointAt(ptr);
return new Point3d(pt[0], pt[1], 0.0);
}
public static void releasePointAt(IntPtr ptr){
UnsafeNativeMethods.releasePointAt(ptr);
}
protected override void Compute(){
int samples = 200;
List<Point3d> points = new List<Point3d>();
InitSamplers();
int pointCount = GeneratePts(samples);
double[] p;
for(int i = 0; i < pointCount - 1; i++)
{
points.Add(getPointAt(i));
}
}
}
}
Итак, внутри моего Compute метода я создаю точки в библиотеке C ++, а затем использую метод getPointsAt для перенести 2D-массив в мою программу. Мой вопрос заключается в том, нужно ли мне затем отпустить указатель обратно в моей библиотеке C ++. Вы можете видеть, что я добавил releasePointAt метод, который должен освободить память, но когда я запускаю его, это приводит к тому, что мое приложение обрабатывает sh. Это работает, если я закомментирую эту строку (поэтому она никогда не освобождает ее), но я не уверен, вызывает ли это утечку памяти или нет. Кто-нибудь может дать какие-либо указания относительно того, нужно ли мне на самом деле отпустить указатель или нет?