从c++ dll中获取结构体到c#应用程序中
Get struct from C++ dll into a C# application
我正在学习c#,并有一些经验。对于一个小项目,我需要在我的c#应用程序中实现一个c++ dll。它是一个车牌识别sdk。我可以初始化它,所以调用这个c++代码是有效的。但是我有一个问题,从c++代码中接收一个结构体,其中包含字符串。我试了很多次,在这里读了很多书,但我没有成功。这是c#端:
[DllImport("D:\processor.dll", EntryPoint = "StartALPR", CallingConvention = CallingConvention.Cdecl)]
[return:MarshalAs(UnmanagedType.LPStruct)]
public static extern TMyData StartALPR(TImageSource tImageSource);
c#结构体TMyData:
[StructLayout(LayoutKind.Sequential)]
public struct TMyData
{
[MarshalAs(UnmanagedType.LPTStr)]
public string PlateString;
[MarshalAs(UnmanagedType.LPTStr)]
public string PlateXML;
[MarshalAs(UnmanagedType.LPTStr)]
public string LastError;
};
这是我们调用来发送tImageSource的方法它包含一个字符串和一个要分析的图像的文件路径。
alprResult = StartALPR(tImageSource);
文件被分析了,所以这是有效的。我可以在VS2015的输出中看到板串。但我期待一个结构体"alprResult"回到TMydata中定义的,但我得到一个异常,方法符号与pinvoke符号不兼容。我所拥有的唯一信息是如何在c++中使用此dll/代码的示例。下面是c++代码:
TImageSource SImageSource;
TMyData *pd;
/* Set input image */
SImageSource.MyImageFile = AnsiString(CarImage).c_str();
Memo1->Lines->Clear();
/* Starting plate detect and recognition */
pd = StartALPR(&SImageSource);
/* Standard XML result, the plate datas with numbers and positions */
Memo1->Lines->Add(pd->PlateXML);
/* last error message */
Memo2->Lines->Add(pd->LastError);
/* Best characters on plate */
Edit1->Text = pd->PlateString;
这是同一个例子中的c++结构体:
struct TMyData;
typedef TMyData *PMyData;
struct TMyData
{
/**
PlateString: Best license plate number of the plate group
*/
const char * PlateString;
/**
PlateXML: Plate group data in standard XML string
*/
const char * PlateXML;
/**
LastError: Laast config error ex: bad file extensions .. Default: empty
*/
const char * LastError;
};
如何在c#中使用它?
实际上我最近不得不解决一个类似的问题。我只是将数据序列化到一个结构体中,并通过本地zeromq套接字发送。
//
// Weather update server in C++
// Binds PUB socket to tcp://*:5556
// Publishes random weather updates
//
// Olivier Chamoux <olivier.chamoux@fr.thalesgroup.com>
//
#include <zmq.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#if (defined (WIN32))
#include <zhelpers.hpp>
#endif
#define within(num) (int) ((float) num * random () / (RAND_MAX + 1.0))
int main () {
// Prepare our context and publisher
zmq::context_t context (1);
zmq::socket_t publisher (context, ZMQ_PUB);
publisher.bind("tcp://*:5556");
publisher.bind("ipc://weather.ipc"); // Not usable on Windows.
// Initialize random number generator
srandom ((unsigned) time (NULL));
while (1) {
int zipcode, temperature, relhumidity;
// Get values that will fool the boss
zipcode = within (100000);
temperature = within (215) - 80;
relhumidity = within (50) + 10;
// Send message to all subscribers
zmq::message_t message(20);
snprintf ((char *) message.data(), 20 ,
"%05d %d %d", zipcode, temperature, relhumidity);
publisher.send(message);
}
return 0;
}
和现在的客户端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using ZeroMQ;
namespace Examples
{
static partial class Program
{
public static void WUClient(string[] args)
{
//
// Weather update client
// Connects SUB socket to tcp://127.0.0.1:5556
// Collects weather updates and finds avg temp in zipcode
//
// Author: metadings
//
if (args == null || args.Length < 2)
{
Console.WriteLine();
Console.WriteLine("Usage: ./{0} WUClient [ZipCode] [Endpoint]", AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine();
Console.WriteLine(" ZipCode The zip code to subscribe. Default is 72622 Nürtingen");
Console.WriteLine(" Endpoint Where WUClient should connect to.");
Console.WriteLine(" Default is tcp://127.0.0.1:5556");
Console.WriteLine();
if (args.Length < 1)
args = new string[] { "72622", "tcp://127.0.0.1:5556" };
else
args = new string[] { args[0], "tcp://127.0.0.1:5556" };
}
string endpoint = args[1];
// Socket to talk to server
using (var context = new ZContext())
using (var subscriber = new ZSocket(context, ZSocketType.SUB))
{
string connect_to = args[1];
Console.WriteLine("I: Connecting to {0}…", connect_to);
subscriber.Connect(connect_to);
/* foreach (IPAddress address in WUProxy_GetPublicIPs())
{
var epgmAddress = string.Format("epgm://{0};239.192.1.1:8100", address);
Console.WriteLine("I: Connecting to {0}…", epgmAddress);
subscriber.Connect(epgmAddress);
}
} */
// Subscribe to zipcode
string zipCode = args[0];
Console.WriteLine("I: Subscribing to zip code {0}…", zipCode);
subscriber.Subscribe(zipCode);
// Process 10 updates
int i = 0;
long total_temperature = 0;
for (; i < 20; ++i)
{
using (var replyFrame = subscriber.ReceiveFrame())
{
string reply = replyFrame.ReadString();
Console.WriteLine(reply);
total_temperature += Convert.ToInt64(reply.Split(' ')[1]);
}
}
Console.WriteLine("Average temperature for zipcode '{0}' was {1}°", zipCode, (total_temperature / i));
}
}
}
}
相关文章:
- 将数组/对象/结构列表从C#库中传递给C MFC应用程序
- 它是否需要为webrtc本机应用程序中的每个对等体提供单独的rtc::Runnable线程和PeerConnection
- 嵌入式设备中传感器应用程序设计体系结构
- 将C 结构传递到C#应用程序
- 将C结构包装在WPF应用程序中
- 使用 Qt 的简单线程 gui 应用程序的结构是什么?
- C++:使用 API 的应用程序体系结构
- 将结构的列表从C#应用程序传递到C++DLL
- 如何为搜索应用程序找到正确的数据结构
- 在C++效率结构中创建日历应用程序
- 在Android应用程序(Java和XML)中使用C++结构
- 完全与视图层无关的应用程序体系结构
- 标识应用程序的体系结构
- 构建应用程序时出错:体系结构 armv7 的未定义符号
- 适用于应用程序级集合的适当体系结构
- 我什么时候需要一个无锁的数据结构来跨音频应用程序中的线程读取/写入数据
- 编译Qt应用程序时出现体系结构x86_64的重复符号错误
- 初始化两个不同应用程序的cpp文件共享的headerfile中的数组结构
- 从c++ dll中获取结构体到c#应用程序中
- 如何从类库返回一个结构体数组到控制台应用程序