首页 > 编程语言 >c++ stdcall 方式与 C# 传递 struct 数据类型?

c++ stdcall 方式与 C# 传递 struct 数据类型?

时间:2023-04-10 15:14:10浏览次数:44  
标签:__ handle struct C# 数据类型 myStruct int length pointerList

using namespace std;
#include <iostream>
#include <thread>
#include <mutex>

struct MyStruct {
    char* myString;
    int length;
    // other members
};

#ifdef __cplusplus
extern "C" {
#endif

    __declspec(dllexport) int __stdcall MyFunction(MyStruct* myStruct);
    __declspec(dllexport) void __stdcall ClearMyFunction(int handle);

#ifdef __cplusplus
}
#endif

static map <int, intptr_t> pointerList;
static std::mutex pointerListLocker;
static int pointerHandleIndex = 0;

int addToPointerList(intptr_t buffer)
{
    pointerListLocker.lock();

    pointerHandleIndex++;
    pointerList.insert(pair<int, intptr_t>(pointerHandleIndex, buffer));

    int ret = pointerHandleIndex;

    pointerListLocker.unlock();

    return ret;
}

intptr_t getFromPointerList(int handle) 
{
    pointerListLocker.lock();

    intptr_t ret = pointerList[handle];

    pointerListLocker.unlock();

    return ret;
}

void removeFromPointerList(int handle)
{
    pointerListLocker.lock();

    map <int, intptr_t>::iterator finder = pointerList.find(handle);
    if (finder != pointerList.end())
        pointerList.erase(handle);

    pointerListLocker.unlock();
}

__declspec(dllexport) int __stdcall MyFunction(MyStruct* myStruct)
{
    char* buffer = new char[myStruct->length + 1];
    strncpy(buffer, myStruct->myString, myStruct->length);
    buffer[myStruct->length] = '\0';

    cout << "c++ from c#:" << buffer << endl;

    delete[] buffer;

    char* buffer2 = new char[] {"Nice to meet you! 幸会"};
    myStruct->myString = buffer2;
    myStruct->length = strlen(buffer2);

    //buffer2使用new声明,需要释放,缓存到pointerList,可调用ClearMyFunction释放
    int handle = addToPointerList(reinterpret_cast<intptr_t>(buffer2));
    return handle;
}

__declspec(dllexport) void __stdcall ClearMyFunction(int handle)
{
    intptr_t pointer = getFromPointerList(handle);
    char* buffer2 = reinterpret_cast<char*>(pointer);
    delete buffer2;
    removeFromPointerList(handle);
}

// 定义 DllMain 函数,用于在 DLL 加载和卸载时执行初始化和清理工作
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        cout << "DLL_PROCESS_ATTACH" << endl;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace ConsoleApp1
{
    internal class Program
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
        public struct MyStruct
        {
            public IntPtr myString;
            public int length;
        }

        [DllImport(@"windows\x64\Debug\OpenCVDemo.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern int MyFunction(ref MyStruct myStruct);

        [DllImport(@"windows\x64\Debug\OpenCVDemo.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern void ClearMyFunction(int handle);

        static void Main(string[] args)
        {
            string inputStr = "Hello, World! 你好!";

            MyStruct myStruct = new MyStruct();
            myStruct.length = inputStr.Length;
            myStruct.myString = Marshal.StringToHGlobalAnsi(inputStr);
            IntPtr pointer = myStruct.myString;

            int handle = MyFunction(ref myStruct);

            string outputStr = Marshal.PtrToStringAnsi(myStruct.myString, myStruct.length);

            Console.WriteLine("Input string: " + inputStr);
            Console.WriteLine("Output string: " + outputStr);

            Marshal.FreeHGlobal(pointer);

            ClearMyFunction(handle);

            Console.ReadLine();
        }
    }
}

 

标签:__,handle,struct,C#,数据类型,myStruct,int,length,pointerList
From: https://www.cnblogs.com/nanfei/p/17302951.html

相关文章

  • 《c++徒步》MFC篇——新建MFC项目
    VS2019安装MFC原文链接:https://blog.csdn.net/qq_36556893/article/details/899459431.打开vs安装程序2.选择VisualStudio扩展开发3.选择C++MFC生成工具(x86和x64)进行安装4.选择修改,等待安装VS2008新建MFC原文链接:https://www.likecs.com/show-454706.htmlVS2008......
  • cf-div2-856c
    题目链接:https://codeforces.com/contest/1816/problem/C我是傻逼,否了自己的第一直觉。。。思路:构造方法:以最后一个值的数值\(x\)为基准,把所有的的数字(除第一个)调整为\(x\)。以n的奇偶性分为两种情况。当n为奇数时:\(第一个数字y小于等于x,构造成功。否则就除了第一个数字外......
  • Consolas是一套等宽字体的字型,属无衬线字体
    等宽字体的字型Consolas是一套等宽字体的字型,属无衬线字体,由LucasdeGroot设计。......
  • 动力节点王鹤SpringBoot3笔记——第六章 远程访问@HttpExchange[SpringBoot 3]
    第六章 远程访问@HttpExchange[SpringBoot3]远程访问是开发的常用技术,一个应用能够访问其他应用的功能。SpringBoot提供了多种远程访问的技术。基于HTTP协议的远程访问是支付最广泛的。SpringBoot3提供了新的HTTP的访问能力,通过接口简化HTTP远程访问,类似Feign功能。Spring......
  • PCIE&IIC 基本概念&图解串行通信协议
       rootcomplex是一切的根,向下生长的是pcie链路      PCI-Express是继ISA和PCI总线之后的第三代I/O总线,即3GIO。由Intel在2001年的IDF上提出,由PCI-SIG(PCI特殊兴趣组织)认证发布后才改名为“PCI-Express”。它的主要优势就是数据传输速率高,另外还有抗干扰能力......
  • 解决WebService部署时出现的“未能创建类型...”错误
       这几天正在学习WebService,但是在部署时老是出现“未能创建类型...”的错误,在IIS7.0下折腾了半天,终于成功部署,现将经验向大家奉上。   首先必须先在IIS在创建一个虚拟目录(这个就不用多说了吧),如果这个时候直接在浏览器里调用WebService就会出现......
  • clayui clayui使用配置
                  在使用CLAYUI前需要对您的工程做如下设置:DebugMultithreadedDLL或者MultithreadedDLL                      VC6下具体设置为:Project-Settings-C/C++,Category选择CodeGeneration,                   ......
  • clayui clayui界面库0.1版发布
    clayui界面库0.1版发布,预览如下:                     clayui是一个免费的,轻量级的界面库,界面开发人员可以通过它轻松的创建界面元素的动画效果,它也可以载入定制的FLASH文件作为界面的皮肤,clayui将界面输出到一个预先定义好的32位图象缓冲区,所以,开发人员......
  • clayui简介
    clayui是一个采用纯C++编写的界面框架,可以很方便的移植到各种系统上。现在支持的系统包括android,windows,wince,linux。clayui的特点是能实现各种2D,3D动画,一些WPF,FLEX才能实现的界面效果,通过clayui可以很方便的实现。clayui的底层渲染支持纯软件渲染,d3d,opengles硬件加速渲染,您可......
  • clayui实用系列(一):在C#里切换窗口时使用各种3D/2D眩酷特效,多达13种特效。
       预览:         下载     这次clayui给大家带来了比较实用的东西,因为时间比较仓促,就先放出C#版,目前只有13种特效,因为做这个本身也比较麻烦,所以想先看看大家的反应吧,如果大家觉得不好用,或者不够眩的话,就不继续下去了。当然,如果大家对这个比较喜欢的话,会......