杜小姐的bug人生 2024-10-31 19:57 采纳率: 54.5%
浏览 19
已结题

C++dll二次开发,C#调用

背景:
将原有的SoftwareDog.dll,移植到C#程序中,实现其原有的授权加密功能。
问题:
运行时,总是在Create的时候遇到问题。查了资料说修改为X64平台也不行

img

C#源码

using System;
using System.Runtime.InteropServices;
namespace ConsoleApp2
{
    class Program
    {
        private static IntPtr myClassInstance;
        [DllImport("DLLDOGCHECK.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern IntPtr CreateMyClass();

        [DllImport("DLLDOGCHECK.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern void DeleteMyClass(IntPtr obj);

        [DllImport("DLLDOGCHECK.dll", CallingConvention = CallingConvention.Cdecl)]
        private static extern int CallInitDog(IntPtr obj);
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            Console.WriteLine("start");
            myClassInstance = CreateMyClass();
            Console.WriteLine("CreateMyClass");
            int nRet = 0;
            nRet = CallInitDog(myClassInstance);
            Console.WriteLine($"CallInitDog={nRet}");
        }
    }
}


C++ 头文件


```c++
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DLLDOGCHECK_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// DLLDOGCHECK_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef DLLDOGCHECK_EXPORTS
#define DLLDOGCHECK_API __declspec(dllexport)
#else
#define DLLDOGCHECK_API __declspec(dllimport)
#endif
#include <string>
#include <atlstr.h>
// 此类是从 dll 导出的

typedef int (*HS_InitSoftwareDog)(char* _pstrDogID, char* _pstrExpireTime, char* _pstrAuthority, char* _pstrDeveloperNo);
typedef int (*HS_GetDogNowTime)(char* _pstrNowTime);
typedef int (*HS_GetDeviceNo)(char* _pstrLocateNo, char* _pstrDogDeviceNo);
class DLLDOGCHECK_API CDllDogCheck {
    // TODO: 在此处添加方法。
public:
    CDllDogCheck(void);
    BOOL InitDog(CString& strError);

    BOOL InitDogSub(CString& strError);
    void GetExepath(TCHAR* pPath);
    BOOL LoadLib(void);
    void FreeLib(void);
    UINT CheckDogThread();

    HS_InitSoftwareDog m_pInitSoftwareDog;
    HS_GetDogNowTime m_pGetDogNowTime;
    HS_GetDeviceNo m_pGetDeviceNo;

    HMODULE m_hModule;

    CString m_strDogID;        // 狗ID
    CString m_strExpireTime;    // 到期时间
    CString m_strAuthority;    // 权限

    CString m_strDogErrorMsg;
    BOOL m_bExit;

};



extern "C" {
    extern DLLDOGCHECK_API int nDllDogCheck;

    DLLDOGCHECK_API int fnDllDogCheck(void);

    DLLDOGCHECK_API int CallInitDog(CDllDogCheck* Obj);

    DLLDOGCHECK_API CDllDogCheck* CreateMyClass();

    DLLDOGCHECK_API void DeleteMyClass(CDllDogCheck* Obj);
}



C++ .CPP
```c++
// DllDogCheck.cpp : 定义 DLL 的导出函数。
//

#include "framework.h"
#include "DllDogCheck.h"


// 这是导出变量的一个示例
DLLDOGCHECK_API int nDllDogCheck=0;

// 这是导出函数的一个示例。
DLLDOGCHECK_API int fnDllDogCheck(void)
{
    return 0;
}

// 这是已导出类的构造函数。
CDllDogCheck::CDllDogCheck()
{
    return;
}

BOOL CDllDogCheck::InitDog(CString& strError)
{
    if (!InitDogSub(strError))
    {
        m_strDogErrorMsg = strError;
    }
    if (!m_strDogErrorMsg.IsEmpty())
    {
        strError = m_strDogErrorMsg;
        return FALSE;
    }
    return TRUE;
}

BOOL CDllDogCheck::InitDogSub(CString& strError)
{
    if (LoadLib() == NULL)
    {
        strError = _T("Fail to Load SoftWareDog.dll");
        return FALSE;
    }
    char  pstrDogID[100] = { 0 };
    char pstrExpireTime[100] = { 0 };
    char pstrAuthority[100] = { 0 };
    char pstrDescription[100] = { 0 };
    char pstrDevelopNo[100] = { 0 };
    char pstrDogDevelopNo[100] = { 0 };
    int nItem = m_pInitSoftwareDog(pstrDogID, pstrExpireTime, pstrAuthority, pstrDescription);
    if (nItem != 0)
    {
        strError = _T("加密狗错误");
        return FALSE;
    }

    nItem = m_pGetDeviceNo(pstrDevelopNo, pstrDogDevelopNo);
    if (nItem != 0)
    {
        strError = _T("加密狗错误");
        return FALSE;
    }

    CString strDogDevelopNo(pstrDogDevelopNo);
    if (strDogDevelopNo.Find(_T("-------")) > -1)
    {
        strError = _T("加密狗错误");
        return FALSE;
    }

    CString strDescription(pstrDescription);
    strDescription.Trim();
    if (strDescription != _T("AAAA"))
    {
        strError = _T("加密狗错误");
        return FALSE;
    }
    return TRUE;
}

void CDllDogCheck::GetExepath(TCHAR* pPath)  //获取执行目录
{
    TCHAR pExePath[256];
    ::memset(pExePath, 0, sizeof(TCHAR) * 256);
    GetModuleFileName(NULL, pExePath, 256);
    TCHAR* pEnd = _tcsrchr(pExePath, '\\');
    *(pEnd + 1) = NULL;
    if (pPath)
    {
        _tcscpy_s(pPath, 256, pExePath);
    }
    return;
}

BOOL CDllDogCheck::LoadLib(void)
{
    TCHAR pszPath[1024] = { 0 };
    GetExepath(pszPath);
    CString strPathTemp(pszPath);
    CString strMarkLib;
    strMarkLib.Format(_T("%sSoftWareDog.dll"), strPathTemp);

    m_hModule = LoadLibrary(strMarkLib);
    int nErr = GetLastError();


    if (m_hModule == NULL)
        return FALSE;

    m_pInitSoftwareDog = (HS_InitSoftwareDog)GetProcAddress(m_hModule, (LPSTR)1);
    m_pGetDogNowTime = (HS_GetDogNowTime)GetProcAddress(m_hModule, (LPSTR)2);
    m_pGetDeviceNo = (HS_GetDeviceNo)GetProcAddress(m_hModule, (LPSTR)3);

    return m_pInitSoftwareDog && m_pGetDogNowTime && m_pGetDeviceNo;
}

void CDllDogCheck::FreeLib(void)
{
    if (m_hModule)
    {
        FreeLibrary(m_hModule);
    }
    m_hModule = NULL;
    m_pInitSoftwareDog = NULL;
    m_pGetDogNowTime = NULL;
    m_pGetDeviceNo = NULL;
}

HANDLE hDogSts = ::CreateEvent(NULL, TRUE, FALSE, NULL);



UINT CDllDogCheck::CheckDogThread()
{
    CString strError;
    if (!InitDogSub(strError))
    {
        m_strDogErrorMsg = strError;
    }
    SetEvent(hDogSts);
    return 0;
}

DLLDOGCHECK_API CDllDogCheck* CreateMyClass()
{
    return new CDllDogCheck();
}

DLLDOGCHECK_API void DeleteMyClass(CDllDogCheck* Obj)
{
    delete Obj;
}

DLLDOGCHECK_API int CallInitDog(CDllDogCheck* Obj)
{
    CString strError;
    if (Obj->InitDog(strError))
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "framework.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}



  • 写回答

30条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-10-31 20:18
    关注

    以下回复引自免费微信小程序:皆我百晓生。 如问题解决,还请采纳。如仍有疑问,请回复留言或私信博主,以便获得更精准的帮助。

    C++DLL的二次开发在C#中可能遇到的问题是:

    1. 编译错误:如果在创建或使用C++ DLL时遇到了编译错误,可能是由于系统配置不匹配、库包未正确链接或者版本不兼容等原因。
    2. 调试失败:在调试C#代码时,有时会出现无法识别和执行目标代码的情况,这可能是因为C#与C++之间的差异导致的。
    3. 导出失败:如果你尝试导出C#类的对象,但是没有找到相应的C++类,则需要确保你的C#代码和C++代码都是兼容的,并且它们都在同一个命名空间下。
    4. 应用程序兼容性问题:如果你的应用程序对不同的操作系统有不同的API接口,那么在C#中编写和运行C++代码可能会出现问题。

    解决方法:

    1. 检查编译器设置:确认你使用的C++语言编译器是否支持C#编译,以及它是否已经添加了正确的库包。
    2. 确认C#与C++之间的兼容性:确保C#代码和C++代码都包含相同的命名空间,并且C#中的所有API都兼容C++。
    3. 重新构建项目:如果上述步骤都无法解决问题,可以考虑重写或者修改C#代码以使其与C++兼容。
    4. 使用第三方库:如果以上步骤都不能解决问题,可以考虑使用第三方库来简化你的C#代码。

    对于C#来说,你需要了解C++库的特性,熟悉如何使用这些库,以便更好地完成任务。另外,C#和C++之间可能存在差异,因此理解它们的工作原理是非常重要的。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月7日
  • 赞助了问题酬金15元 10月31日
  • 修改了问题 10月31日
  • 创建了问题 10月31日

悬赏问题

  • ¥25 LT码在高斯信道下的误码率仿真
  • ¥45 渲染完成之后将物体的材质贴图改变,自动化进行这个操作
  • ¥15 yolov5目标检测并显示目标出现的时间或视频帧
  • ¥15 电视版的优酷可以设置电影连续播放吗?
  • ¥50 复现论文;matlab代码编写
  • ¥30 echarts 3d地图怎么实现一进来页面散点数据和卡片一起轮播
  • ¥15 数字图像的降噪滤波增强
  • ¥15 心碎了,为啥我的神经网络训练的时候第二个批次反向传播会报错呀,第一个批次都没有问题
  • ¥15 MSR2680-XS路由器频繁卡顿问题
  • ¥15 VB6可以成功读取的文件,用C#读不了