Создание внешних компонент 1С NativeAPI на C++. Часть 2

Добавим функцию:

long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface)
{
    if(!*pInterface)
    {
        *pInterface= new Component;
        return (long)*pInterface;
    }
    return 0;
}

В ней у нас используется тип IComponentBase, который нам необходимо описать. Для этого в файлах заголовках добавляем:

В него добавляем следующий код:

/*
 *          Warning!!!
 *       DO NOT ALTER THIS FILE!
 */


#ifndef __COMPONENT_BASE_H__
#define __COMPONENT_BASE_H__

#include "types.h"
////////////////////////////////////////////////////////////////////////////////
/**
 *  The given interface is intended for initialization and 
 *  uninitialization of component and its adjustments
 */
/// Interface of component initialization.
class IInitDoneBase
{
public:
    virtual ~IInitDoneBase() {}
    /// Initializes component
    /**
     *  @param disp - 1C:Enterpise interface
     *  @return the result of
     */
    virtual bool ADDIN_API Init(void* disp) = 0;
    /// Sets the memory manager
    /*
     * @param mem - pointer to memory manager interface.
     *  @return the result of
     */
    virtual bool ADDIN_API setMemManager(void* mem) = 0;

    /// Returns component version
    /**
     *  @return - component version (2000 - version 2)
     */
    virtual long ADDIN_API GetInfo() = 0;

    /// Uninitializes component
    /**
     *  Component here should release all consumed resources.
     */
    virtual void ADDIN_API Done() = 0;

};
///////////////////////////////////////////////////////////////////////////
/**
 *  The given interface defines methods that are intented to be used by the Platform
 */
/// Interface describing extension of language.
class ILanguageExtenderBase
{
public:
    virtual ~ILanguageExtenderBase(){}
    /// Registers language extension
    /**
     *  @param wsExtensionName - extension name
     *  @return the result of
     */
    virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T** wsExtensionName) = 0;

    /// Returns number of component properties
    /**
     *  @return number of properties
     */
    virtual long ADDIN_API GetNProps() = 0;

    /// Finds property by name
    /**
     *  @param wsPropName - property name
     *  @return property index or -1, if it is not found
     */
    virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName) = 0;

    /// Returns property name
    /**
     *  @param lPropNum - property index (starting with 0)
     *  @param lPropAlias - 0 - international alias,
     *      1 - russian alias. (International alias is required)
     *  @return proeprty name or 0 if it is not found
     */
    virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum,  
						 long lPropAlias) = 0;

    /// Returns property value
    /**
     *  @param lPropNum - property index (starting with 0)
     *  @param pvarPropVal - the pointer to a variable for property value
     *  @return the result of
     */
    virtual bool ADDIN_API GetPropVal(const long lPropNum, 
				      tVariant* pvarPropVal) = 0;

    /// Sets the property value
    /**
     *  @param lPropNum - property index (starting with 0)
     *  @param varPropVal - the pointer to a variable for property value
     *  @return the result of
     */
    virtual bool ADDIN_API SetPropVal(const long lPropNum, 
				      tVariant* varPropVal) = 0;

    /// Is property readable?
    /**
     *  @param lPropNum - property index (starting with 0)
     *  @return true if property is readable
     */
    virtual bool ADDIN_API IsPropReadable(const long lPropNum) = 0;

    /// Is property writable?
    /**
     *  @param lPropNum - property index (starting with 0)
     *  @return true if property is writable
     */
    virtual bool ADDIN_API IsPropWritable(const long lPropNum) = 0;

    /// Returns number of component methods
    /**
     *  @return number of component  methods
     */
    virtual long ADDIN_API GetNMethods() = 0;

    /// Finds a method by name 
    /**
     *  @param wsMethodName - method name
     *  @return - method index
     */
    virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName) = 0;

    /// Returns method name
    /**
     *  @param lMethodNum - method index(starting with 0)
     *  @param lMethodAlias - 0 - international alias,
     *      1 - russian alias. (International alias is required)
     *  @return method name or 0 if method is not found
     */
    virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum, 
						   const long lMethodAlias) = 0;

    /// Returns number of method parameters
    /**
     *  @param lMethodNum - method index (starting with 0)
     *  @return number of parameters
     */
    virtual long ADDIN_API GetNParams(const long lMethodNum) = 0;

    /// Returns default value of method parameter
    /**
     *  @param lMethodNum - method index(starting with 0)
     *  @param lParamNum - parameter index (starting with 0)
     *  @param pvarParamDefValue - the pointer to a variable for default value
     *  @return the result of
     */
    virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, 
					    const long lParamNum,
					    tVariant *pvarParamDefValue) = 0;

    /// Does the method have a return value?
    /**
     *  @param lMethodNum - method index (starting with 0)
     *  @return true if the method has a return value
     */
    virtual bool ADDIN_API HasRetVal(const long lMethodNum) = 0;

    /// Calls the method as a procedure
    /**
     *  @param lMethodNum - method index (starting with 0)
     *  @param paParams - the pointer to array of method parameters
     *  @param lSizeArray - the size of array
     *  @return the result of
     */
    virtual bool ADDIN_API CallAsProc(const long lMethodNum,
				      tVariant* paParams, 
				      const long lSizeArray) = 0;

    /// Calls the method as a function
    /**
     *  @param lMethodNum - method index (starting with 0)
     *  @param pvarRetValue - the pointer to returned value
     *  @param paParams - the pointer to array of method parameters
     *  @param lSizeArray - the size of array
     *  @return the result of
     */
    virtual bool ADDIN_API CallAsFunc(const long lMethodNum,
				      tVariant* pvarRetValue, 
				      tVariant* paParams, 
				      const long lSizeArray) = 0;    
};
///////////////////////////////////////////////////////////////////////////
/**
 *  This interface is used to change component locale
 */
/// Base interface for component localization.
class LocaleBase
{
public:
    virtual ~LocaleBase(){}
    /// Changes component locale
    /**
     *  @param loc - new locale (for Windows - rus_RUS, 
     *      for Linux - ru_RU, etc...)
     */
    virtual void ADDIN_API SetLocale(const WCHAR_T* loc) = 0;
};
///////////////////////////////////////////////////////////////////////////
/**
 *  The given interface is generalized, for its obligatory inheritance 
 *  in implementing components.
 */
///  Base interface describing object as a set of properties and methods.
class IComponentBase :
public IInitDoneBase,
    public ILanguageExtenderBase,
    public LocaleBase
{
public:
    virtual ~IComponentBase(){}
};

/// Announcements of exported functions
/**
 * These functions should be implemented that component can be loaded and created. 
 */
extern "C" long GetClassObject(const WCHAR_T*, IComponentBase** pIntf);
extern "C" long DestroyObject(IComponentBase** pIntf);
extern "C" const WCHAR_T* GetClassNames();

typedef long (*GetClassObjectPtr)(const WCHAR_T* wsName, IComponentBase** pIntf);
typedef long (*DestroyObjectPtr)(IComponentBase** pIntf);
typedef const WCHAR_T* (*GetClassNamesPtr)();

#endif //__COMPONENT_BASE_H__

В основном файле добавляем строку:

#include "ComponentBase.h"

Добавляем новый класс в файл Component.h:

// class Component
class Component : public IComponentBase
{
public:
    enum Props
    {
        ePropLast = 0       // Always last
    };

    enum Methods
    {
        eVersion = 0,       // Версия Компоненты

        eMethLast           // Always last
    };

    Component(void);
    virtual ~Component();

};

Добавим файл types.h с содержимым:


#ifndef __CON_TYPES_H__
#define __CON_TYPES_H__

#ifndef __linux__
#include <windows.h>
#endif

#if __GNUC__ >=3
#pragma GCC system_header
#endif

#include "com.h"
#include <time.h>
#include <string.h>
#include <assert.h>
#include <stddef.h>

#define EXTERN_C extern "C"

#ifdef __GNUC__
#define _ANONYMOUS_UNION __extension__
#define _ANONYMOUS_STRUCT __extension__
#else
#define _ANONYMOUS_UNION 
#define _ANONYMOUS_STRUCT 
#endif //__GNUC__

#ifdef NONAMELESSUNION
#define __VARIANT_NAME_1 u
#define __VARIANT_NAME_2 iface
#define __VARIANT_NAME_3 str
#define __VARIANT_NAME_4 wstr
#else
#define __VARIANT_NAME_1
#define __VARIANT_NAME_2
#define __VARIANT_NAME_3
#define __VARIANT_NAME_4
#endif //NONAMELESSUNION

#define RESULT_FROM_ERRNO(x)     ((long)(x) <= 0 ? ((long)(x)) \
: ((long) (((x) & 0x0000FFFF) | (BASE_ERRNO << 16) | 0x80000000)))

#define ADDIN_E_NONE 1000
#define ADDIN_E_ORDINARY 1001
#define ADDIN_E_ATTENTION 1002
#define ADDIN_E_IMPORTANT 1003
#define ADDIN_E_VERY_IMPORTANT 1004
#define ADDIN_E_INFO 1005
#define ADDIN_E_FAIL 1006
#define ADDIN_E_MSGBOX_ATTENTION 1007
#define ADDIN_E_MSGBOX_INFO 1008
#define ADDIN_E_MSGBOX_FAIL 1009

#ifndef  ADDIN_API
#ifndef __linux__
#define ADDIN_API __stdcall
#else
//#define ADDIN_API __attribute__ ((__stdcall__))
#define ADDIN_API
#endif //__linux__
#endif //ADDIN_API

#if !defined __linux__
    ////////////////////////////////////////////////////////////////////////////
    // sized integer types
   // typedef __int8            int8_t   ; ///< 8-bit integer
    typedef unsigned __int8   uint8_t  ; ///< 8-bit unsigned integer

    typedef __int16           int16_t  ; ///< 16-bit integer         
    typedef  unsigned __int16 uint16_t ; ///< 16-bit unsigned integer

    typedef __int32           int32_t  ; ///< 32-bit integer         
    typedef  unsigned __int32 uint32_t ; ///< 32-bit unsigned integer

    typedef __int64           int64_t  ; ///< 64-bit integer         
    typedef  unsigned __int64 uint64_t ; ///< 64-bit unsigned integer
#else        
#include <stdint.h>
#endif    
#ifndef __linux__
#define WCHAR_T     wchar_t
#else
#define WCHAR_T     uint16_t
#endif //__linux__
typedef unsigned short TYPEVAR;
enum ENUMVAR
{   
    VTYPE_EMPTY    = 0,
    VTYPE_NULL,
    VTYPE_I2,                   //int16_t
    VTYPE_I4,                   //int32_t
    VTYPE_R4,                   //float
    VTYPE_R8,                   //double
    VTYPE_DATE,                 //DATE (double)
    VTYPE_TM,                   //struct tm
    VTYPE_PSTR,                 //struct str    string
    VTYPE_INTERFACE,            //struct iface
    VTYPE_ERROR,                //int32_t errCode
    VTYPE_BOOL,                 //bool
    VTYPE_VARIANT,              //struct _tVariant *
    VTYPE_I1,                   //int8_t
    VTYPE_UI1,                  //uint8_t
    VTYPE_UI2,                  //uint16_t
    VTYPE_UI4,                  //uint32_t
    VTYPE_I8,                   //int64_t
    VTYPE_UI8,                  //uint64_t
    VTYPE_INT,                  //int   Depends on architecture
    VTYPE_UINT,                 //unsigned int  Depends on architecture
    VTYPE_HRESULT,              //long hRes
    VTYPE_PWSTR,                //struct wstr
    VTYPE_BLOB,                 //means in struct str binary data contain
    VTYPE_CLSID,                //UUID
    VTYPE_STR_BLOB    = 0xfff,
    VTYPE_VECTOR   = 0x1000,
    VTYPE_ARRAY    = 0x2000,
    VTYPE_BYREF    = 0x4000,    //Only with struct _tVariant *
    VTYPE_RESERVED = 0x8000,
    VTYPE_ILLEGAL  = 0xffff,
    VTYPE_ILLEGALMASKED    = 0xfff,
    VTYPE_TYPEMASK = 0xfff
} ;
#if defined (__GNUC__) && !defined (NONAMELESSUNION)
__extension__   /* no named members  */
#endif
struct _tVariant
{
    _ANONYMOUS_UNION union 
    {
        //int8_t         i8Val;
        int16_t        shortVal;
        int32_t        lVal;
        int            intVal;
        unsigned int   uintVal;
        int64_t        llVal;
        uint8_t        ui8Val;
        uint16_t       ushortVal;
        uint32_t       ulVal;
        uint64_t       ullVal;
        int32_t        errCode;
        long           hRes;
        float          fltVal;
        double         dblVal;
        bool           bVal;
        char           chVal;
        wchar_t        wchVal;
        //DATE           date;
        IID            IDVal;
        struct _tVariant *pvarVal;
        struct tm      tmVal;
        _ANONYMOUS_STRUCT struct 
        {
            void*  pInterfaceVal;
            IID        InterfaceID;
        } __VARIANT_NAME_2/*iface*/;
        _ANONYMOUS_STRUCT struct 
        {
            char*        pstrVal;
            uint32_t     strLen; //count of bytes
        } __VARIANT_NAME_3/*str*/;
        _ANONYMOUS_STRUCT struct 
        {
            WCHAR_T*    pwstrVal;
            uint32_t    wstrLen; //count of symbol
        } __VARIANT_NAME_4/*wstr*/;
    } __VARIANT_NAME_1;
    uint32_t      cbElements;    //Dimension for an one-dimensional array in pvarVal
    TYPEVAR       vt;
};
typedef struct _tVariant    tVariant;
typedef tVariant    tVariantArg;


#if defined(NONAMELESSUNION)
#define TV_JOIN(X, Y)   ((X)->u.Y)
#else
#define TV_JOIN(X, Y)   ((X)->Y)
#endif

#define TV_VT(X)          ((X)->vt)
#define TV_ISBYREF(X)     (TV_VT(X)&VT_BYREF)
#define TV_ISARRAY(X)     (TV_VT(X)&VT_ARRAY)
#define TV_ISVECTOR(X)    (TV_VT(X)&VT_VECTOR)
#define TV_NONE(X)        TV_I2(X)

#define TV_UI1(X)         TV_JOIN(X, ui8Val)
#define TV_I2(X)          TV_JOIN(X, shortVal)
#define TV_I4(X)          TV_JOIN(X, lVal)
#define TV_I8(X)          TV_JOIN(X, llVal)
#define TV_R4(X)          TV_JOIN(X, fltVal)
#define TV_R8(X)          TV_JOIN(X, dblVal)
#define TV_I1(X)          TV_JOIN(X, i8Val)
#define TV_UI2(X)         TV_JOIN(X, ushortVal)
#define TV_UI4(X)         TV_JOIN(X, ulVal)
#define TV_UI8(X)         TV_JOIN(X, ullVal)
#define TV_INT(X)         TV_JOIN(X, intVal)
#define TV_UINT(X)        TV_JOIN(X, uintVal)

#ifdef _WIN64
#define TV_INT_PTR(X)        TV_JOIN(X, llVal)
#define TV_UINT_PTR(X)       TV_JOIN(X, ullVal)
#else
#define TV_INT_PTR(X)        TV_JOIN(X, lVal)
#define TV_UINT_PTR(X)       TV_JOIN(X, ulVal)
#endif


#define TV_DATE(X)        TV_JOIN(X, date)
#define TV_STR(X)         TV_JOIN(X, pstrVal)
#define TV_WSTR(X)        TV_JOIN(X, pwstrVal)
#define TV_BOOL(X)        TV_JOIN(X, bVal)
#define TV_UNKNOWN(X)     TV_JOIN(X, pInterfaceVal)
#define TV_VARIANTREF(X)  TV_JOIN(X, pvarVal)

void tVarInit(tVariant* tvar);

inline
void tVarInit(tVariant* tvar)
{
    assert(tvar != NULL);
    memset(tvar, 0, sizeof(tVariant));
    TV_VT(tvar) = VTYPE_EMPTY;
}
//----------------------------------------------------------------------------//
// static setter functions...

#define DATA_SET_BEGIN(data_)                                         \
    tVarInit(data_);

#define DATA_SET_END(data_, type_)                                    \
    TV_VT(data_) = type_;
    

#define DATA_SET(data_, type_, member_, value_)                       \
    DATA_SET_BEGIN(data_)                                             \
    TV_JOIN(data_, member_) = value_;                                 \
    DATA_SET_END(data_, type_)

#define DATA_SET_WITH_CAST(data_, type_, member_, cast_, value_)      \
    DATA_SET_BEGIN(data_)                                             \
    TV_JOIN(data_, member_) = cast_ value_;                           \
    DATA_SET_END(data_, type_)

#endif //__CON_TYPES_H__

Добавим файл IMemoryManager.h с содержимым:

/*
 *          Warning!!!
 *       DO NOT ALTER THIS FILE!
 */


#ifndef __IMEMORY_MANAGER_H__
#define __IMEMORY_MANAGER_H__

///////////////////////////////////////////////////////////////////////////////
/**
 *  The given class allocates and releases memory for a component
 */
/// Interface representing memory manager.
class IMemoryManager
{
public:
    virtual ~IMemoryManager() {}
    /// Allocates memory of specified size
     /**
     *  @param pMemory - the double pointer to variable, that will hold newly
     *      allocated block of memory of NULL if allocation fails. 
     *  @param ulCountByte - memory size
     *  @return the result of
     */
    virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
    /// Releases memory
     /**
     *  @param pMemory - The double pointer to the memory block being released
     */
    virtual void ADDIN_API FreeMemory (void** pMemory) = 0;
};

#endif //__IMEMORY_MANAGER_H__

Так как класс CComponent наследуется от IComponentBase, то в нем должны быть определенные процедуры. Добавляем в файл Component.h описание функций в public:

   // IInitDoneBase
    virtual bool ADDIN_API Init(void*);
    virtual bool ADDIN_API setMemManager(void* mem);
    virtual long ADDIN_API GetInfo();
    virtual void ADDIN_API Done();
    // ILanguageExtenderBase
    virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T**);
    virtual long ADDIN_API GetNProps();
    virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName);
    virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, long lPropAlias);
    virtual bool ADDIN_API GetPropVal(const long lPropNum, tVariant* pvarPropVal);
    virtual bool ADDIN_API SetPropVal(const long lPropNum, tVariant* varPropVal);
    virtual bool ADDIN_API IsPropReadable(const long lPropNum);
    virtual bool ADDIN_API IsPropWritable(const long lPropNum);
    virtual long ADDIN_API GetNMethods();
    virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName);
    virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum, 
                            const long lMethodAlias);
    virtual long ADDIN_API GetNParams(const long lMethodNum);
    virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, const long lParamNum,
                            tVariant *pvarParamDefValue);   
    virtual bool ADDIN_API HasRetVal(const long lMethodNum);
    virtual bool ADDIN_API CallAsProc(const long lMethodNum,
                    tVariant* paParams, const long lSizeArray);
    virtual bool ADDIN_API CallAsFunc(const long lMethodNum,
                tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray);
    // LocaleBase
    virtual void ADDIN_API SetLocale(const WCHAR_T* loc);

Итоговый текст модуля Component.cpp после добавления реализаций функций:

// Component.cpp : Определяет экспортируемые функции для DLL.
//

#include "pch.h"
#include "framework.h"
#include "Component.h"
#include "ComponentBase.h"

#include <stdio.h>

#include <string.h>
#include <locale.h>

#define TIME_LEN 34
#define BASE_ERRNO     7 

typedef unsigned int       uint32_t;

uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len = 0);
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len = 0);
uint32_t getLenShortWcharStr(const WCHAR_T* Source);

// Пример экспортированной переменной
COMPONENT_API int nComponent=0;

// Пример экспортированной функции.
COMPONENT_API int fnComponent(void)
{
    return 0;
}

static wchar_t *g_PropNames[] = { L"" };
static wchar_t *g_PropNamesRu[] = { L"" };

static wchar_t *g_MethodNamesRu[] = {
                                        L"Версия",
                                        L"ПолучитьФрагментИзображения"
};

static wchar_t* g_MethodNames[] = {
                                        L"Version",
                                        L"GetImageFragment"
};

static const wchar_t g_kClassNames[] = L"C1CGetImageFragment";

//---------------------------------------------------------------------------//

const wchar_t* kComponentVersion = L"1.0";

const wchar_t* kErrMsg_NoImagePath = L"No image path";
const wchar_t* kErrMsg_NoMFCPath = L"No path to application";
const wchar_t* kErrMsg_NoResultPath = L"No result path";

const wchar_t* kErrMsg_LoadImage = L"Error loading image";
const wchar_t* kErrMsg_Timeout = L"Error timeout expired";
const wchar_t* kErrMsg_InternalError = L"Internal error";   // любые внутренние ошибка кода компоненты
const wchar_t* kErrMsg_NoPicturePaths = L"No picture paths";

//---------------------------------------------------------------------------//

const WCHAR_T* GetClassNames()
{
    static WCHAR_T* names = 0;
    if (!names)
        ::convToShortWchar(&names, g_kClassNames);
    return names;
}

uint32_t convToShortWchar(WCHAR_T** Dest, const wchar_t* Source, uint32_t len)
{
    if (!len)
        len = ::wcslen(Source) + 1;

    if (!*Dest)
        *Dest = new WCHAR_T[len];

    WCHAR_T* tmpShort = *Dest;
    wchar_t* tmpWChar = (wchar_t*)Source;
    uint32_t res = 0;

    ::memset(*Dest, 0, len * sizeof(WCHAR_T));
    do
    {
        *tmpShort++ = (WCHAR_T)*tmpWChar++;
        ++res;
    } while (len-- && *tmpWChar);

    return res;
}

//---------------------------------------------------------------------------//
uint32_t convFromShortWchar(wchar_t** Dest, const WCHAR_T* Source, uint32_t len)
{
    if (!len)
        len = getLenShortWcharStr(Source) + 1;

    if (!*Dest)
        *Dest = new wchar_t[len];

    wchar_t* tmpWChar = *Dest;
    WCHAR_T* tmpShort = (WCHAR_T*)Source;
    uint32_t res = 0;

    ::memset(*Dest, 0, len * sizeof(wchar_t));
    do
    {
        *tmpWChar++ = (wchar_t)*tmpShort++;
        ++res;
    } while (len-- && *tmpShort);

    return res;
}
//---------------------------------------------------------------------------//

uint32_t getLenShortWcharStr(const WCHAR_T* Source)
{
    uint32_t res = 0;
    WCHAR_T* tmpShort = (WCHAR_T*)Source;

    while (*tmpShort++)
        ++res;

    return res;
}

//---------------------------------------------------------------------------//

long GetClassObject(const WCHAR_T* wsName, IComponentBase** pInterface)
{
    if (!*pInterface)
    {
        *pInterface = new CComponent;
        return (long)*pInterface;
    }
    return 0;
}

// CComponent
//---------------------------------------------------------------------------//
CComponent::CComponent()
{
    m_iMemory = 0;
    m_iConnect = 0;
}
//---------------------------------------------------------------------------//
CComponent::~CComponent()
{
}

bool CComponent::Init(void* pConnection)
{
    m_iConnect = (IAddInDefBase*)pConnection;
    return m_iConnect != NULL;
}
//---------------------------------------------------------------------------//
long CComponent::GetInfo()
{
    // Component should put supported component technology version 
    // This component supports 2.0 version
    return 2000;
}
//---------------------------------------------------------------------------//
void CComponent::Done()
{
}
/////////////////////////////////////////////////////////////////////////////
// ILanguageExtenderBase
//---------------------------------------------------------------------------//
bool CComponent::RegisterExtensionAs(WCHAR_T** wsExtensionName)
{
    const wchar_t* wsExtension = L"AddInNativeExtension";
    int iActualSize = ::wcslen(wsExtension) + 1;
    WCHAR_T* dest = 0;

    if (m_iMemory)
    {
        if (m_iMemory->AllocMemory((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T)))
            ::convToShortWchar(wsExtensionName, wsExtension, iActualSize);
        return true;
    }

    return false;
}
//---------------------------------------------------------------------------//
long CComponent::GetNProps()
{
    // You may delete next lines and add your own implementation code here
    return ePropLast;
}
//---------------------------------------------------------------------------//
long CComponent::FindProp(const WCHAR_T* wsPropName)
{
    long plPropNum = -1;
    wchar_t* propName = 0;

    ::convFromShortWchar(&propName, wsPropName);
    plPropNum = findName(g_PropNames, propName, ePropLast);

    if (plPropNum == -1)
        plPropNum = findName(g_PropNamesRu, propName, ePropLast);

    delete[] propName;

    return plPropNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CComponent::GetPropName(long lPropNum, long lPropAlias)
{
    if (lPropNum >= ePropLast)
        return NULL;

    wchar_t* wsCurrentName = NULL;
    WCHAR_T* wsPropName = NULL;
    int iActualSize = 0;

    switch (lPropAlias)
    {
    case 0: // First language
        wsCurrentName = g_PropNames[lPropNum];
        break;
    case 1: // Second language
        wsCurrentName = g_PropNamesRu[lPropNum];
        break;
    default:
        return 0;
    }

    iActualSize = wcslen(wsCurrentName) + 1;

    if (m_iMemory && wsCurrentName)
    {
        if (m_iMemory->AllocMemory((void**)&wsPropName, iActualSize * sizeof(WCHAR_T)))
            ::convToShortWchar(&wsPropName, wsCurrentName, iActualSize);
    }

    return wsPropName;
}
//---------------------------------------------------------------------------//
bool CComponent::GetPropVal(const long /*lPropNum*/, tVariant* /*pvarPropVal*/)
{
    return false;
}
//---------------------------------------------------------------------------//
bool CComponent::SetPropVal(const long /*lPropNum*/, tVariant* /*varPropVal*/)
{
    return false;
}
//---------------------------------------------------------------------------//
bool CComponent::IsPropReadable(const long /*lPropNum*/)
{
    return false;
}
//---------------------------------------------------------------------------//
bool CComponent::IsPropWritable(const long /*lPropNum*/)
{
    return false;
}
//---------------------------------------------------------------------------//
long CComponent::GetNMethods()
{
    return eMethLast;
}
//---------------------------------------------------------------------------//
long CComponent::FindMethod(const WCHAR_T* wsMethodName)
{
    long plMethodNum = -1;
    wchar_t* name = 0;

    ::convFromShortWchar(&name, wsMethodName);

    plMethodNum = findName(g_MethodNames, name, eMethLast);

    if (plMethodNum == -1)
        plMethodNum = findName(g_MethodNamesRu, name, eMethLast);

    return plMethodNum;
}
//---------------------------------------------------------------------------//
const WCHAR_T* CComponent::GetMethodName(const long lMethodNum, const long lMethodAlias)
{
    if (lMethodNum >= eMethLast)
        return NULL;

    wchar_t* wsCurrentName = NULL;
    WCHAR_T* wsMethodName = NULL;
    int iActualSize = 0;

    switch (lMethodAlias)
    {
    case 0: // First language
        wsCurrentName = g_MethodNames[lMethodNum];
        break;
    case 1: // Second language
        wsCurrentName = g_MethodNamesRu[lMethodNum];
        break;
    default:
        return 0;
    }

    iActualSize = wcslen(wsCurrentName) + 1;

    if (m_iMemory && wsCurrentName)
    {
        if (m_iMemory->AllocMemory((void**)&wsMethodName, iActualSize * sizeof(WCHAR_T)))
            ::convToShortWchar(&wsMethodName, wsCurrentName, iActualSize);
    }

    return wsMethodName;
}
//---------------------------------------------------------------------------//
long CComponent::GetNParams(const long lMethodNum)
{
    switch (lMethodNum)
    {
    case eVersion:
        return 0;
    default:
        return 0;
    }

    return 0;
}
//---------------------------------------------------------------------------//
bool CComponent::GetParamDefValue(const long lMethodNum, const long lParamNum,
    tVariant* pvarParamDefValue)
{
    TV_VT(pvarParamDefValue) = VTYPE_EMPTY;

    switch (lMethodNum)
    {
    case eVersion:

    default:
        return false;
    }

    return false;
}
//---------------------------------------------------------------------------//
bool CComponent::HasRetVal(const long lMethodNum)
{
    switch (lMethodNum)
    {
    case eVersion:
        return true;
    default:
        return false;
    }

    return false;
}
//---------------------------------------------------------------------------//
bool CComponent::CallAsProc(const long lMethodNum,
    tVariant* paParams, const long lSizeArray)
{
    switch (lMethodNum)
    {
    case eVersion:
    default:
        return false;
    }

    return false;   // as func
}


//---------------------------------------------------------------------------//
bool CComponent::CallAsFunc(const long lMethodNum,
    tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
{
    switch (lMethodNum)
    {
    case eVersion:
    {
        if (pvarRetValue)
        {
            size_t strLen = wcslen(kComponentVersion);
            if (m_iMemory->AllocMemory((void**)&pvarRetValue->pwstrVal, (strLen + 1) * sizeof(kComponentVersion[0])))
            {
                wcscpy_s(pvarRetValue->pwstrVal, strLen + 1, kComponentVersion);
                pvarRetValue->wstrLen = strLen;
                TV_VT(pvarRetValue) = VTYPE_PWSTR;
            }
        }

        break;
    }
    
    default:
        return false;
    }

    return true;
}

//---------------------------------------------------------------------------//
void CComponent::SetLocale(const WCHAR_T* loc)
{
#ifndef __linux__
    _wsetlocale(LC_ALL, loc);
#else
    //We convert in char* char_locale
    //also we establish locale
    //setlocale(LC_ALL, char_locale);
#endif
}
/////////////////////////////////////////////////////////////////////////////
// LocaleBase
//---------------------------------------------------------------------------//
bool CComponent::setMemManager(void* mem)
{
    m_iMemory = (IMemoryManager*)mem;
    return m_iMemory != 0;
}
//---------------------------------------------------------------------------//
void CComponent::addError(uint32_t wcode, const wchar_t* source,
    const wchar_t* descriptor, long code)
{
    if (m_iConnect)
    {
        WCHAR_T* err = 0;
        WCHAR_T* descr = 0;

        ::convToShortWchar(&err, source);
        ::convToShortWchar(&descr, descriptor);

        m_iConnect->AddError(wcode, err, descr, code);
        delete[] err;
        delete[] descr;
    }
}


//---------------------------------------------------------------------------//
void CComponent::addError(const wchar_t* errorText)
{
    if (m_iConnect)
        m_iConnect->AddError(ADDIN_E_NONE, L"C1CGetImageFragment", errorText, 0);
}


//---------------------------------------------------------------------------//
long CComponent::findName(wchar_t* names[], const wchar_t* name,
    const uint32_t size) const
{
    long ret = -1;
    for (uint32_t i = 0; i < size; i++)
    {
        if (!wcscmp(names[i], name))
        {
            ret = i;
            break;
        }
    }
    return ret;
}

Итоговый текст модуля Component.h:

// Приведенный ниже блок ifdef — это стандартный метод создания макросов, упрощающий процедуру
// экспорта из библиотек DLL. Все файлы данной DLL скомпилированы с использованием символа COMPONENT_EXPORTS
// Символ, определенный в командной строке. Этот символ не должен быть определен в каком-либо проекте,
// использующем данную DLL. Благодаря этому любой другой проект, исходные файлы которого включают данный файл, видит
// функции COMPONENT_API как импортированные из DLL, тогда как данная DLL видит символы,
// определяемые данным макросом, как экспортированные.
#ifdef COMPONENT_EXPORTS
#define COMPONENT_API __declspec(dllexport)
#else
#define COMPONENT_API __declspec(dllimport)
#endif

#include "ComponentBase.h"
#include "AddInDefBase.h"
#include "IMemoryManager.h"

extern COMPONENT_API int nComponent;

COMPONENT_API int fnComponent(void);

// class Component
class CComponent : public IComponentBase
{
public:
    enum Props
    {
        ePropLast = 0       // Always last
    };

    enum Methods
    {
        eVersion = 0,       // Версия Компоненты

        eMethLast           // Always last
    };

    CComponent(void);
    virtual ~CComponent();
    // IInitDoneBase
    virtual bool ADDIN_API Init(void*);
    virtual bool ADDIN_API setMemManager(void* mem);
    virtual long ADDIN_API GetInfo();
    virtual void ADDIN_API Done();
    // ILanguageExtenderBase
    virtual bool ADDIN_API RegisterExtensionAs(WCHAR_T**);
    virtual long ADDIN_API GetNProps();
    virtual long ADDIN_API FindProp(const WCHAR_T* wsPropName);
    virtual const WCHAR_T* ADDIN_API GetPropName(long lPropNum, long lPropAlias);
    virtual bool ADDIN_API GetPropVal(const long lPropNum, tVariant* pvarPropVal);
    virtual bool ADDIN_API SetPropVal(const long lPropNum, tVariant* varPropVal);
    virtual bool ADDIN_API IsPropReadable(const long lPropNum);
    virtual bool ADDIN_API IsPropWritable(const long lPropNum);
    virtual long ADDIN_API GetNMethods();
    virtual long ADDIN_API FindMethod(const WCHAR_T* wsMethodName);
    virtual const WCHAR_T* ADDIN_API GetMethodName(const long lMethodNum,
        const long lMethodAlias);
    virtual long ADDIN_API GetNParams(const long lMethodNum);
    virtual bool ADDIN_API GetParamDefValue(const long lMethodNum, const long lParamNum,
        tVariant* pvarParamDefValue);
    virtual bool ADDIN_API HasRetVal(const long lMethodNum);
    virtual bool ADDIN_API CallAsProc(const long lMethodNum,
        tVariant* paParams, const long lSizeArray);
    virtual bool ADDIN_API CallAsFunc(const long lMethodNum,
        tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray);
    // LocaleBase
    virtual void ADDIN_API SetLocale(const WCHAR_T* loc);

private:
    
    long findName(wchar_t* names[], const wchar_t* name, const uint32_t size) const;
    void addError(uint32_t wcode, const wchar_t* source,
        const wchar_t* descriptor, long code);

    // добавление ошибки в Предприятие в момент вызова функции компоненты
    void addError(const wchar_t* errorText);

    // Attributes
    IAddInDefBase* m_iConnect;
    IMemoryManager* m_iMemory;

    bool                m_boolEnabled;
    uint32_t            m_uiTimer;
};

После всего этого пробуем собрать проект. Возможно будет ошибка преобразования wchar_t, для решения можно поменять настройки проекта:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *