0

This Code is copied directly from the website commitcrm.com It is a demostration on how to use their API ( Like Hello World, it connects to an database, creates an account, and update that account )

It compiles perfect on Windows XP + Delphi 2007 and the executable works perfect.

If the exact same code is compiled on Windows 7 + Delphi XE2/XE5/XE7 then executable gives error :(

I have found that it is somehow related to Char / Ansichar, pChar / PAnsiChar.

Because, when I change the char to ansichar for the CmtInitDbEngDll procedure, it actually connect to the database. Great.

But I am not able to (I am not good enough) find out what I have to change...should it be char, ansichar, pchar, pansichar and so on, because I am not sure how to handle it when a DLL is involved.

Is there any smart delphi people who can help ?

------ SOURCE CODE ----------------------------------------------------

program Demo;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes;

const
 C_DataBuffSize = 1024;
 C_MapBufSize = 1024;
 C_ErrMsgBuffSize = 1024;
 C_DescSize = 1024;
 C_ErrCodeBuffSize = 64;
 C_RecIDBuffSize = 64;

 C_Flag = 1;
 C_Ok = 1;
 C_AccountsTable = 10;
 C_AppName = 'Demo';

 CmtDbEngDll = 'C:\CommitCRM\ThirdParty\UserDev\CmtDbEng.DLL';

var
 Status: integer;
 DataBuff: array [0..C_DataBuffSize] of Char;
 MapBuff: array [0..C_MapBufSize] of Char;
 RecIdBuff: array [0..C_RecIDBuffSize] of Char;
 ErrCodesBuff: array [0..C_ErrCodeBuffSize] of Char;
 ErrMsgBuff: array [0..C_ErrMsgBuffSize] of Char;
 s: string;

//** Establishing connection with CommitCRM, Should be called only once for the entire session *
Procedure CmtInitDbEngDll (
             xSoftWareName   : PChar; // Your application name. Once selected this  string
                                      // will be used for all
                                      // functions of the package. Specify a meaningful value.
             xDbPath         : PChar; // Path to the DB folder under where CommitCRM server is
                                      // installed <server>\CommitCRM\Db

             var xvStatus     : integer           // Returned connection status
            ); stdcall; external CmtDbEngDll;

//**** Insert/Update record
Procedure CmtInsUpdRec(
             xSoftWareName   : pChar;            // See above
             xDataKind           : integer;      // Desired Table Code
             xDataBuff           : pChar;        // String containing the values, which we want
                                                 // to add into the Database
             xMapBuff            : pChar;        // List of the database fields into
                                                 //which we want to add data
             xContWhenInvalidData : Integer;     //Flag - stop(0)/continue(1) the input process
                                                 // is some data value(s) is invalid
             xFlags                : Integer;              // Not used
             xRecIDBuffLen      : Integer;          // Length of REC ID Buffer
             xLogErrCodesBuffLen  : Integer;  // Length of Error Code Buffer
             xLogErrMsgBuffLen     : Integer;     // Length of Error Message Buffer
             xvRecIDBuff          : pChar;            // Buffer for returned REC ID
             xvErrCodesLogBuff : pChar;         // Buffer for returned Error Codes
             xvErrMsgLogBuff    : pChar;         // Buffer for returned Error Messages
              var xvStatus       : Integer          // Returned status
             ); stdcall; external CmtDbEngDll;

//**** Terminate connection with CommitCRM ****
procedure CmtTerminateDbEngDll; stdcall; external CmtDbEngDll;

procedure CmtGetDescriptionByCode(
                                 xCode     : Integer;
                                 xDescLen  : Integer;
                                 xvDesc    : pChar); stdcall; external CmtDbEngDll;

procedure CmtGetDescriptionByStatus(
                                   xCode     : Integer;
                                   xDescLen  : Integer;
                                   xvDesc    : pChar); stdcall; external CmtDbEngDll;

procedure ErrCodesParsing (ErrCodeBuff: string);
var
 lList: TStringList;
 i: integer;
 aDescErrCode : Pchar;
begin
 try
   lList := TStringList.Create;
   lList.Text := ErrCodeBuff;
   GetMem(aDescErrCode,C_DescSize);
   for i := 0 to lList.Count - 1 do
   begin
     CmtGetDescriptionByCode(StrToInt(lList[i]), C_DescSize, aDescErrCode);
     writeln('Error Code: '+lList[i]+' Desc: '+string(aDescErrCode));
   end;
 finally
   FreeMem(aDescErrCode);
   lList.Destroy;
 end;
end;

procedure DisplayErrStatusCode(xCode : Integer);
var
 aStatusErrCode : Pchar;
begin
 try
   GetMem(aStatusErrCode,C_DescSize);
   CmtGetDescriptionByStatus(xCode,C_DescSize, aStatusErrCode);
   writeln('Commit Init failed. Error code: '+Inttostr(xCode)+' Desc: '+string(aStatusErrCode));
 finally
   FreeMem(aStatusErrCode);
 end;
end;

begin

 //**** Establishing connection with CommitCRM, Should be called only once for the entire session
 CmtInitDbEngDll(C_AppName, // Your application name. Once selected this string will be used
                            // for all functions of the package. Specify a meaningful value.
  'C:\CommitCRM\Db\',                    // Path to the DB folder under where CommitCRM server is
                                          // installed <server>\CommitCRM\Db
  Status                   // Returned connection status
   );

 if Status = C_Ok then
 begin

   //**** Insert a new Account into the Accounts table ****

   s := '"Bart De Hantsetters","De Hantsetters","Hantsetters"';
   StrPCopy(DataBuff, s);
   s := '"'+#13','+#13+'FLDCRDFULLNAME'+#13+'FLDCRDDEAR'+#13+'FLDCRDCONTACT'+#0;
   StrPCopy(MapBuff, s);

    CmtInsUpdRec(C_AppName,         // Your application name
                 C_AccountsTable,   // Desired Table Code
                 DataBuff,          // String containing the values, which we want to add into
                                    // the Database
                 MapBuff,           // List of the Database Fields in which we want to add data
                 C_Flag,            // Flag - stop(0)/continue(1) the input process is some data
                                    // value(s) is invalid
                 0,                             // Not used
                 C_RecIDBuffSize,         // Llength of REC ID Buffer
                 C_ErrCodeBuffSize,      // Length of Error Code Buffer
                 C_ErrMsgBuffSize,       // Length of Error Message Buffer
                 RecIdBuff,                 // Buffer for returned REC ID
                 ErrCodesBuff,             // Buffer for returned Error Codes
                 ErrMsgBuff,                // Buffer for returned Error Messages
                 Status                      // Returned status
         );



   if (ErrMsgBuff[0] <> #0) then
     writeln('Error Message: '+ ErrMsgBuff);

   ErrCodesParsing(ErrCodesBuff);

   if Status = C_Ok then
   begin
 //**** Updating the Account record we've just created *****

     // Map file for the update transaction - the Dear field and the record id
     s := '"'+#13+','+#13+'FLDCRDDEAR'+#13'FLDCRDRECID';
     StrPCopy(MapBuff, s);

     s := '"Doctor","'+RecIdBuff+'"';
     StrPCopy(DataBuff, s);

     CmtInsUpdRec(C_AppName,           // Your application name
                  C_AccountsTable,     // Desired Table Code
                  DataBuff,            // String containing  the values, which we want
                                       // to add into the Database
                  MapBuff,             // List of the database fields into which we want to add
                                       //data
                  C_Flag,              // Flag - stop(0)/continue(1) the input process is some
                                       // data value(s) is invalid
                  0,                   // Not used
                  C_RecIDBuffSize,     // Length of REC ID Buffer
                  C_ErrCodeBuffSize,   // Length of Error Code Buffer
                  C_ErrMsgBuffSize,    // Length of Error Message Buffer
                  RecIdBuff,           // Buffer for returned RECID
                  ErrCodesBuff,        // Buffer for returned Error Codes
                  ErrMsgBuff,          // Buffer for returned Error Messages
                  Status               // Returned status
         );

     if ((ErrMsgBuff[0] <> #0)) then
       writeln('Error Message: '+ ErrMsgBuff);

     ErrCodesParsing(ErrCodesBuff);

     if Status = C_Ok then
       Writeln('Completed Successfully');
   end
   else
   begin
     try
       s := IntToStr(Status);
     except
       s := 'ill-defined';
     end;
     writeln('Insert new Account. Error code: '+ s);
   end;

 //**** Terminate connection with CommitCRM****

   CmtTerminateDbEngDll();
 end
 else
 begin
   DisplayErrStatusCode(Status);
 end;

 writeln(#13#10+'press Enter to quit');
 readln;
end.
IT NET
  • 63
  • 3
  • 10

1 Answers1

1

Delphi up to and including Delphi 2007 was basically 8-bit ANSI. Delphi 2009 and later are Unicode.

Here are two links that might help:

Embarcadero introduced full Unicode support in RAD Studio for the first time in August of 2008. In doing so, they ensured that Delphi an d C++Builder would remain at the forefront of native application development on the Wind ows platform for a very long time to come.

However, unlike many of the other major enhancements that have been introduced in Delphi over the years, such as variants and interfaces (Delphi 3), frames (Delphi 5), function inlining and nested classes (Delphi 2005) and generics (RAD Studio 2009), enabling Unicode didn't involve simply adding new features to what was already supported in Delphi. Instead, it involved a radical change to several fundamental data types that appear in nearly every Delphi application. Specifically, the definitions for the String, Char, and PChar types changed.

These changes were not adopted lightly. Instead, they were introduced only after extensive consideration for the impact that these changes would have for existing applications as well as how they would affect future development. In addition, Embarcadero sought the input and advice of many of its Technology Partners who support and promote Delphi.

In reality, there was no way to implement the Unicode support without some inconvenience. ...

The String type is now defined by the UnicodeString type, which is a UTF-16 string. Similarly, Char type is now WideChar, a two-byte character type, and PChar is a PWideChar, a pointer to a two-byte Char.

The significant point about the changes to these basic data types is that, at a minimum, each character is represented by at least one code unit (two bytes), and sometimes more.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
FoggyDay
  • 11,962
  • 4
  • 34
  • 48