cancel
Showing results for 
Search instead for 
Did you mean: 

type F in SAP with some problems when sent from SAP to .NET

Former Member
0 Kudos

Hi,

I'm using .Net SAP connector to call a C# function from SAP and I'm having a problem with type F variables when I put them inside a structure.

When I fill a type F var. in SAP with a value,ex: 123, it reaches C# with that value, but if this variable is inside a structure the same value reaches C# as 4.6618078678049E-305 (a very small value).

Can you tell me what is wrong, is this a bug of the connector, or I need to do something before sending the values into C#?

Thanks,

Luis Pinho

This is the code:

ABAP:

REPORT SAMPLE_REPORT.

data:

f32_value type F,

BEGIN OF IFX_F32_Struct OCCURS 1,

IFX_PK(20) type C,

IFX_F32 type F,

END OF IFX_F32_Struct,

f32_arr like IFX_F32_Struct OCCURS 0 WITH HEADER LINE,

IFX_ETX(350) type C,

IFX_ECD type I.

f32_value = 123.

f32_arr-IFX_PK = '0'.

f32_arr-IFX_F32 = 123.

append f32_arr.

clear f32_arr.

f32_arr-IFX_PK = '0'.

f32_arr-IFX_F32 = 32.

append f32_arr.

clear f32_arr.

f32_arr-IFX_PK = '0'.

f32_arr-IFX_F32 = 800.

append f32_arr.

clear f32_arr.

call function 'SAMPLE' destination 'YODA_PROXY'

EXPORTING

f32_value = f32_value

IMPORTING

IFX_ETX = IFX_ETX

IFX_ECD = IFX_ECD

TABLES

f32_arr = f32_arr

.

write: / '----


'.

write: / 'IFX_ECD =', IFX_ECD.

write: / 'IFX_ETX =',(130) IFX_ETX.

write: / '----


'.

C# (abstract):

using System;

using System.Xml.Serialization;

using SAP.Connector;

namespace SAPApp

{

/// <summary>

/// Summary description for SAPAbstractClass.

/// </summary>

public abstract class SAPAbstractClass: SAPServer

{

// Constructors

public SAPAbstractClass(){}

public SAPAbstractClass(string ConnectionString) :base(ConnectionString){}

public SAPAbstractClass(string connectionString, SAPServerHost host) : base(connectionString, host) {}

public SAPAbstractClass(string[] args) : base(args) {}

public SAPAbstractClass(string[] args, SAPServerHost host) : base(args, host) {}

public SAPAbstractClass(string programId, string gwhost, string sapgwxx, string codepage): base(programId, gwhost, sapgwxx, codepage) {}

public SAPAbstractClass(string programId, string gwhost, string sapgwxx, string codepage, SAPServerHost host): base(programId, gwhost, sapgwxx, codepage, host) {}

[RfcMethod(AbapName="SAMPLE")]

protected abstract void SAMPLE(

[RfcParameter(AbapName="F32_VALUE",RfcType=RFCTYPE.RFCTYPE_FLOAT,Optional= false, Direction = RFCINOUT.IN )]

[XmlElement("F32_VALUE", IsNullable=false)]

double /f32/ F32_VALUE,

[RfcParameter(AbapName="F32_ARR",RfcType=RFCTYPE.RFCTYPE_ITAB,Optional= false, Direction = RFCINOUT.IN )]

[XmlElement("F32_ARR", IsNullable=false)]

IFX_F32_ARRAYTable F32_ARR,

[RfcParameter(AbapName="IFX_ETX",RfcType=RFCTYPE.RFCTYPE_CHAR,Optional= false, Direction = RFCINOUT.OUT, Length = 350 )]

[XmlElement("IFX_ETX", IsNullable=false)]

out string IFX_ETX,

[RfcParameter(AbapName="IFX_ECD",RfcType=RFCTYPE.RFCTYPE_INT,Optional= false, Direction = RFCINOUT.OUT)]

[XmlElement("IFX_ECD", IsNullable=false)]

out int IFX_ECD);

}

[RfcStructure(AbapName="IFX_F32_Struct", Length= 28)]

public class IFX_F32_ARRAY : SAPStructure

{

[RfcField(AbapName = "IFX_PK", RfcType = RFCTYPE.RFCTYPE_CHAR, Length = 20, Offset = 0)]

[XmlElement("IFX_PK")]

public string IFX_PK

{

get

{

return IFXPK;

}

set

{

IFXPK = value;

}

}

private string IFXPK;

[RfcField(AbapName = "IFX_F32", RfcType = RFCTYPE.RFCTYPE_FLOAT, Length = 8, Offset = 20)]

[XmlElement("IFX_F32")]

public double IFX_F32

{

get

{

return IFXF32;

}

set

{

IFXF32 = value;

}

}

private double IFXF32;

}

public class IFX_F32_ARRAYTable : SAPTable

{

public static Type GetElementType()

{

return (typeof(IFX_F32_ARRAY));

}

public override object CreateNewRow()

{

return new IFX_F32_ARRAY();

}

public IFX_F32_ARRAY this[int index]

{

get

{

return ((IFX_F32_ARRAY)(List[index]));

}

set

{

List[index] = value;

}

}

public int Add(IFX_F32_ARRAY value)

{

return List.Add(value);

}

public void Insert(int index, IFX_F32_ARRAY value)

{

List.Insert(index, value);

}

public int IndexOf(IFX_F32_ARRAY value)

{

return List.IndexOf(value);

}

public bool Contains(IFX_F32_ARRAY value)

{

return List.Contains(value);

}

public void Remove(IFX_F32_ARRAY value)

{

List.Remove(value);

}

public void CopyTo(IFX_F32_ARRAY[] array, int index)

{

List.CopyTo(array, index);

}

}

}

C# implementation:

using System;

using System.Collections;

using SAP.Connector;

namespace SAPApp

{

/// <summary>

/// Summary description for SAPImpl.

/// </summary>

public class SAPImpl: SAPAbstractClass

{

public SAPImpl(string[] args, SAPServerHost host) : base(args, host)

{

}

public SAPImpl()

{

}

protected override void SAMPLE(double /f32/ F32_VALUE, IFX_F32_ARRAYTable F32_ARR, out string IFX_ETX, out int IFX_ECD)

{

/* start of initialization of out parameters*/

IFX_ECD = 0;

IFX_ETX = "";

/* end of initialization of out parameters*/

try

{

Console.WriteLine(" Message Received ");

/* End of preparation of the request */

/* Start of the conversion of the in parameters from SAP into YODA and fill of the request doc*/

Console.WriteLine("f32_value" + F32_VALUE.ToString());

if (F32_ARR!=null)

{

for (int i_0=0;i_0<F32_ARR.Count;i_0++)

{

Console.WriteLine(i_0 + " " + F32_ARR[i_0].IFX_F32);

}

}

}

catch(Exception ex)

{

/* exception throwned */

IFX_ECD = -1;

IFX_ETX = ex.Message;

Console.WriteLine(ex);

return;

}

}

}

}

C# main

using System;

using SAP.Connector;

namespace SAPApp

{

/// <summary>

/// Summary description for Class1.

/// </summary>

class MainClass

{

/// <summary>

/// The main entry point for the application.

/// </summary>

static void Main(string[] args)

{

SAPServerHost host = new SAPServerHost();

SAPImpl server = null;

try

{

const int numberOfServers = 1;

for(int i = 0; i < numberOfServers; i++)

{

Console.WriteLine("Create RFC Server SAPImpl instance {0}" ,i);

server = new SAPImpl(args,host);

server.ProgramID = "YODA_PROXY";

Console.WriteLine("PROG_ID: " + server.ProgramID);

Console.WriteLine("GW_HOST: " + server.SAPGatewayHost);

}

try

{

Console.WriteLine("Start RFC Server SAPServerStubImpl instances");

host.Start();

}

catch(Exception e)

{

Console.WriteLine(e.Message);

Console.WriteLine("Hit RETURN to exit!");

Console.ReadLine();

return;

}

Console.WriteLine("To stop SAPServerStubImpl, please enter Stop!");

string command = "";

do

{

command = Console.ReadLine();

switch (command)

{

case "Stop":

host.Stop();

Console.WriteLine("All SAPServerStubImpl instances stopped.");

break;

case "Start":

host.Start();

Console.WriteLine("All SAPServerStubImpl instances started.");

break;

case "Pause":

host.Pause();

Console.WriteLine("All SAPServerStubImpl instances paused.");

break;

case "Continue":

host.Continue();

Console.WriteLine("All SAPServerStubImpl instances resumed.");

break;

case "Clear":

host.RemoveAllSAPServers();

Console.WriteLine("All SAPServerStubImpl instances stopped and removed.");

break;

case "Exit":

host.Stop();

Console.WriteLine("All SAPServerStubImpl instances stopped and program exits.");

break;

}

}while(command != "Exit");

}

catch(Exception ex)

{

Console.WriteLine("Fatal Error occurred !!!");

Console.WriteLine("Message of exception" + ex.Message);

host.Stop();

host.Start();

}

}

}

}

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Hi,

obviously, you are still handcrafting the RfcFieldAttribute instead of using SAP's wizard to generate code for you.

The offset for the field IFX_F32 in your hand-made structure is wrong. The correct value in this case should be 24.

As already said, it is not recommended to set Rfc related attributes by hand.

Regards,

Guangwei

Former Member
0 Kudos

Hi Guangwei,

Unfortunaly I cannot use the wizard because the services that I'm mapping are not available on a SAP server, they are in a complex C# class. The proxies I'm generating make these class methods available for SAP users.

So I'm making a generator that acts like the wizard, it builds code so that persons can access it.

About the offset, shouldn't this be offset = offset + length of last parameter?

The first parameter is a string with a length = 20, so the offset of the next parameter (in this case a float) will be 20, right? The size of the F type if 8, right?

I used your wizard to create a proxy for a BAPI that has a float parameter in one of the used tables, and I noticed that it had an extra attribute Decimals = 16, I added this attribute but I've got no improvement.

(I also tried to put a offset = 24 with no good results)

Former Member
0 Kudos

Hi Nuno,

RFC requires that the fields within a structure must be naturally aligned, that means:

offset >= offset + length of last field

and

offset % length == 0

After you changing the offset from 20 to 24, you should also change the total length of the structure within the RfcStructureAttribute.

The parameter with extra attribute Decimal is for ABAP type P (or BCD) which is corresponding to decimal in C#.

ABAP type F is mapped to double in C#.

Regards,

Guangwei

Former Member
0 Kudos

Thanks, I would never guess that one (offset % length == 0), I will apply this to my code.

Thanks again,

Luís Pinho

Answers (0)