gpt4 book ai didi

c++ - 如何将对象(或指针)从 C++ .NET 应用程序发送到 VB 应用程序

转载 作者:IT老高 更新时间:2023-10-28 22:41:28 27 4
gpt4 key购买 nike

我有 2 个应用程序。

VB 应用程序 是用 .NET 3.5 编写的。这是一个相当大的应用程序。由于几个原因,我无法将其重写为 C++。我不确定这是否重要,但它是 x86 应用程序。

C++ 应用程序 是用 .NET 4.0 编写的。它是 x64 版本,将不支持 x86。现在 - 它是带有一些汇编代码的托管代码。稍后当我了解有关 C++ 的更多信息时,我将混合托管和非托管。它是 x64 版本,必须保持这种状态。

它应该扩展 VB 应用程序的功能 - 从相机捕获帧,对它们进行处理并将处理后的图像发送到 VB 应用程序。图像非常大(1920x1080x24bpp),我需要每秒处理 30-60 帧,所以它必须是有效的方式。

我的目标:

  1. 将位图从 C++ 应用程序“发送”到 VB 应用程序,当该位图到达时,VB 应用程序应该启动一些方法。

  2. 以另一种方式“发送”一些信息,从 VB 应用程序到 C++ 应用程序。它应该从 VB 应用程序 GUI 更改 C++ 应用程序处理参数。

  3. 如果可能 - 只发送一个指针和位图大小,而不是在 RAM 中复制整个数据。


可以说,我想要这样的东西:

VB端:

Function receivedBitmapFromCpp(BMP_POINTER?, BMP_SIZE_X?, BMP_SIZE_Y?, BMP_BPP?) As Integer Handles ????

End Function

C++ 方面:

void sendBitmapToVb(BMP_POINTER?, BMP_SIZE_X?, BMP_SIZE_Y?, BMP_BPP?)
{
int bitmapsendingresult = ?????
}

它可能是 System.Drawing.Bitmap,或者只是一些我将在 VB 应用程序中转换为 System.Drawing.Bitmap 的数组。没关系。


我的问题:

谁能解释一下,我该怎么做:

  • 发送一些对象数据(例如 System.Drawing.Bitmap),或从 VB 应用程序到 C++ 应用程序的更好的指向该数据的指针
  • 在 C++ 应用程序中接收该数据
  • 在接收/准备好数据时启动一些 C++ 函数(带有一些事件?)

最佳答案

使用共享内存循环缓冲区在进程之间交换数据。这可以使用 boost interprocess 作为 C++ dll 来实现,然后可以将该 dll 导入到您的 .Net 应用程序中。请注意,您将需要构建 32 位和 64 位版本的 boost 和您的共享内存 dll。我准备了一个 32 位和 64 位应用程序的示例,您可以运行它们,看看它有多快。我认为它应该足够快,但如果不是那么仍然可以使用多线程。

64 位生产者:

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <chrono>

struct shmem_info
{
boost::interprocess::interprocess_mutex mutex;
uint64_t pos;
bool run;
};

int main(int argc, char *argv[])
{
using namespace boost::interprocess;

struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); shared_memory_object::remove("MySharedMemoryInfo");}
//~shm_remove() { shared_memory_object::remove("MySharedMemory"); shared_memory_object::remove("MySharedMemoryInfo");}
} remover;
const size_t width = 1920;
const size_t height = 1080;
const size_t bytes_per_pixel = 3;
const size_t frame_size = width*height*bytes_per_pixel;
const size_t frames = 60;
const size_t shmem_frames = 3 * frames;
const size_t shmem_size = width * height * bytes_per_pixel * shmem_frames;

std::cout << "Generating data ..." << std::endl;
std::vector<uint8_t> frame(frame_size);

// generate frame data
for (size_t x = 0; x < width*height; ++x)
for (size_t y = 0; y < bytes_per_pixel; ++y)
frame[x*bytes_per_pixel + y] = (x%252) + y;

std::cout << "Creating shared memory files ..." << std::endl;
shared_memory_object shm(create_only, "MySharedMemory", read_write);
shared_memory_object shm_info(create_only, "MySharedMemoryInfo", read_write);

//Set size
shm.truncate(shmem_size);
shm_info.truncate(sizeof(shmem_info));

//Map the whole shared memory in this process
mapped_region region(shm, read_write);
mapped_region region_info(shm_info, read_write);

shmem_info *info = new (region_info.get_address()) shmem_info;
{
scoped_lock<interprocess_mutex> lock(info->mutex);
info->pos = 0;
info->run = true;
}

char c;
std::cout << "Ready. Now start client application and wait for it to be ready." << std::endl;
std::cout << "Then press a key and enter to start" << std::endl;
std::cin >> c;
std::cout << "Running ..." << std::endl;

std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
size_t times = 10;
for (size_t t = 0; t < times; ++t)
{
for (size_t f = 0; f < shmem_frames; ++f)
{
// get pointer to the beginning of shared memory
uint8_t *ptr = static_cast<uint8_t*>(region.get_address());
// move pointer to the next frame
ptr += f*frame_size;

// modify first data point for testing purposes
frame[0] = f;
frame[1] = f + 1;
frame[2] = f + 2;

// copy data to shared memory
memcpy(ptr, &frame[0], frame_size);

// update the position each "frames" number, doing that too frequently kills the performance
if (f % frames == 0)
{
// this will lock access to the pos for the time of updating the pos only
scoped_lock<interprocess_mutex> lock(info->mutex);
info->pos += frames;
std::cout << "write pos = " << info->pos << std::endl;
}
}
}

std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
size_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << (double(times*shmem_frames*1000) / double(ms)) << " fps." << std::endl;

winapi::sleep(2000);

// stop run
{
scoped_lock<interprocess_mutex> lock(info->mutex);
info->run = false;
}

return 0;
}

32 位消费者:

#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <chrono>

struct shmem_info
{
boost::interprocess::interprocess_mutex mutex;
uint64_t pos;
bool run;
};

int main(int argc, char *argv[])
{
using namespace boost::interprocess;

const size_t width = 1920;
const size_t height = 1080;
const size_t bytes_per_pixel = 3;
const size_t frame_size = width*height*bytes_per_pixel;
const size_t frames = 60;
const size_t shmem_frames = 3 * frames;
const size_t shmem_size = width * height * bytes_per_pixel * shmem_frames;

std::vector<uint8_t> frame(frame_size);

std::cout << "Opening shared memory files ..." << std::endl;

//Open already created shared memory object.
shared_memory_object shm(open_only, "MySharedMemory", read_write);
shared_memory_object shm_info(open_only, "MySharedMemoryInfo", read_write);

//Map the whole shared memory in this process
mapped_region region(shm, read_only);
mapped_region region_info(shm_info, read_write);

shmem_info *info = static_cast<shmem_info*>(region_info.get_address());

std::cout << "Ready." << std::endl;

bool run = true;

// first wait for processing to be started
while (true)
{
{
scoped_lock<interprocess_mutex> lock(info->mutex);
if (info->run)
break;
}
winapi::Sleep(1);
}

std::chrono::steady_clock::time_point start = std::chrono::steady_clock::now();
uint64_t pos = 0;
uint64_t shm_pos = 0;
while(run)
{
// wait for a new data
{
scoped_lock<interprocess_mutex> lock(info->mutex);
run = info->run;
if (info->pos == pos)
{
winapi::Sleep(1);
continue;
}
// we've got the new data
shm_pos = info->pos;
}

while (pos < shm_pos)
{
// get pointer to the beginning of shared memory
uint8_t *ptr = static_cast<uint8_t*>(region.get_address());
// calculate the frame position in circular buffer and move pointer to that frame
ptr += (pos%shmem_frames)*frame_size;

// copy data from shared memory
memcpy(&frame[0], ptr, frame_size);

//winapi::Sleep(1);
++pos;
if (pos % frames == 0)
std::cout << "read pos: " << pos << std::endl;
}
}

std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
size_t ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
ms -= 2000; // producer waits 2 seconds before sets run=false
std::cout << (double(pos*1000) / double(ms)) << " fps." << std::endl;

return 0;
}

我使用 boost 1.58,第一个循环总是很慢,您可能需要在开始使用共享内存之前运行一个热身循环。需要将数据复制到共享内存中,但是为了读取指向帧的 shmem 指针,可以将其传递给 .Net 应用程序。然后,您需要确保您的 .Net 应用在数据被覆盖之前按时读取数据。

有用的链接:

boost interpocess

Simple example

编辑:我修改了源代码以显示大致可以达到的每秒帧数。在我的机器上是 190+ fps,所以考虑到在 .Net 应用程序和 c++ dll 之间传输数据/指针的开销,我希望它仍然高于所需的 60 fps。


上面的代码应该给你一个好的开始,你需要将生产者和消费者共享内存代码重构为一个公共(public)类并使其成为一个dll。将 c++ dll 导入 .Net 的方法很少。 How-to-Marshal-a-C-Class其中一些解释得很好。

现在回答你的问题:

Can someone explain, how can I:

send some object data (like System.Drawing.Bitmap for example), or better pointer to that data from VB application to C++ application

您需要使用 GetHbitmap() 方法从 Bitmap 获取 HBITMAP 并将其传递给 c++ dll。然后在 c++ dll 中,如果需要,将像素数据和其他位图信息复制到共享内存中(指向数据的指针不起作用)。如何在 .Net 和 c++ 之间执行此操作,请参阅 c-get-raw-pixel-data-from-hbitmap . this answer 特别有用.

receive that data in C++ application

然后要从共享内存中读取数据,您可能需要首先创建与共享内存中大小相同的空 Bitmap,并将其 HBITMAP 传递给 C++ dll 以填充像素数据。

start some C++ function (with some event?) when data is received/ready

您只需要像上面的代码一样不断地轮询共享内存以获取新数据。

关于c++ - 如何将对象(或指针)从 C++ .NET 应用程序发送到 VB 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31449582/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com