SUShadowInfoGetValue return wrong type

calling SUShadowInfoGetValue with “ShadowTime_time_t” doesn’t return an error but when checking the returned type with SUTypedValueGetType it is SUTypedValueType_Int32 as oppose to SUTypedValueType_Time and SUTypedValueGetTime return SU_ERROR_NO_DATA while SUTypedValueGetInt32 return 2 as the epoch for today’s date!!?

Anyone else have this problem?

This might be correct as using the "ShadowTime_time_t" argument is synonymous with calling the Ruby core Time#to_i method. (Note that the C API’s docs call it “Epoch Time” which is weird. I’ve never heard it called that anywhere else.)

Basically it returns the Integer number of seconds since the beginning of the current Epoch.

In the Ruby API …

model = Sketchup.active_model
shadowinfo = model.shadow_info
#<Sketchup::ShadowInfo:0x00021e483cb870>
t = shadowinfo["ShadowTime_time_t"]
#=> 1573219800
t.class
#=> Bignum
t.is_a?(Integer)
#=> true

In the Ruby core Time class introduction find this …

Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer, Bignum or Rational. The integer is a number of nanoseconds since the Epoch which can represent 1823-11-12 to 2116-02-20. When Bignum or Rational is used (before 1823, after 2116, under nanosecond), Time works slower as when integer is used.

At one time (no pun intended) I thought that Ruby was using the UNIX epoch …

Wikipedia:
The Unix epoch is the time 00:00:00 UTC on 1 January 1970.

And the C API also says …

SUTypedValueGetTime

Retrieves the time value of a typed value object.
The time value is in seconds since January 1, 1970.


This is correct. An integer number of seconds is not equal to an object that represents Time. In the Ruby API it uses the Ruby core Time class.

I don’t see a file in the C API for time like I’d expect.

You need to call this with the typed value out from the call to SUShadowInfoGetValue function.

I’ve got no idea how to actually get today’s date or time with the C API. It’s easy with Ruby using the Time class.

You can do this from C if you need to. (EDIT / ADD: Something like this):

#include "ruby.h"

static int getCurrentTime() {
    int t;
    VALUE time = rb_eval_string("Time.now.to_i");
    t = NUM2INT(time);
    return t;
}

If it’s a long instead of an int, then use the Ruby C macro NUM2LONG instead.

(All the numeric conversion macros are listed on pg 11 of the “Writing Ruby Extensions in C” book.)

Can you provide a code sample?

When testing the two keys I see expected results.

int _tmain(int argc, _TCHAR* argv[])
{
  SUInitialize();

  SUModelRef model = SU_INVALID;
  SU(SUModelCreate(&model));
  //SU(SUModelCreateFromFile(&model, model_path.c_str()));

  SUShadowInfoRef shadow_info = SU_INVALID;
  SU(SUModelGetShadowInfo(model, &shadow_info));

  SUTypedValueRef value = SU_INVALID;
  SUTypedValueType type;
  SU(SUTypedValueCreate(&value));

  SU(SUShadowInfoGetValue(shadow_info, "ShadowTime_time_t", &value));
  SU(SUTypedValueGetType(value, &type)); // SUTypedValueType_Int32
  int32_t epoc_time;
  auto result = SUTypedValueGetInt32(value, &epoc_time);
  if (result == SU_ERROR_NONE) {
    std::cout << "ShadowTime_time_t: Type: " << type << " - Value: " << epoc_time << "\n";
  } else {
    std::cout << "ShadowTime_time_t: Error:" << result << "\n";
  }
  
  SU(SUShadowInfoGetValue(shadow_info, "ShadowTime", &value));
  SU(SUTypedValueGetType(value, &type)); // SUTypedValueType_Time
  time_t time;
  result = SUTypedValueGetTime(value, &time);
  if (result == SU_ERROR_NONE) {
    std::cout << "ShadowTime: Type: " << type << " - Value: " << time << "\n";
  }
  else {
    std::cout << "ShadowTime: Error:" << result << "\n";
  }

  SU(SUTypedValueRelease(&value));

  SU(SUModelRelease(&model));

  SUTerminate();
  return 0;
}

Output:

ShadowTime_time_t: Type: 3 - Value: 1561123800
ShadowTime: Type: 8 - Value: 1561123800

The crux is the word “expected”.

The list of SUShadowInfo keys (in the C API docs) does not tell the reader what to expect.

He did not know "ShadowTime_time_t" would give an integer number of seconds since the Epoch.

A C API coder needs to read the doc for SUTypedValueGetTime in order to have an expectation.

Docs assume some familiarity of C/C++.

https://en.cppreference.com/w/c/chrono/time_t

Although not defined by the C standard, this is almost always an integral value holding the number of seconds (not counting leap seconds) since 00:00, Jan 1 1970 UTC, corresponding to POSIX time.

The docs assume too much.

If the docs had 1 small sentence, then this entire thread and all it’s posts and words would not have wasted our time.

1 Like

My mistake, I was passing the value from SUModelGetRenderingOptions instead of the value from SUModelGetShadowInfo.

I used rb_num2int(rb_eval_string(‘Sketchup.active_model.shadow_info[“ShadowTime_time_t”]’)); at first when I didn’t know how to get the shadow info, then Dan mention about the rendering options and I got it mixed up. That’s why the time_t gave me an error and epoch = 2, sorry guys. That’s why I hate to convert my code, got to learn new API and it’s not as friendly as expected, with all the checks it’s easy to miss a simple mistake. Al that coding just to get the date.

We learn best by our mistakes. :wink:

2 Likes