[PATCH 1/5] widl: Handle aggregate returns in a MSVC compatible way.

Henri Verbeet hverbeet at codeweavers.com
Fri Sep 5 08:50:56 CDT 2014


Aggregates are returned through an implicit parameter after the this/interface
pointer. Note that this follows the C++ convention, affected methods are not
callable from C with the Microsoft headers.
---
 dlls/d2d1/brush.c         |   20 +++++++--------
 dlls/d2d1/render_target.c |   19 +++++++-------
 tools/widl/header.c       |   60 ++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 70 insertions(+), 29 deletions(-)

diff --git a/dlls/d2d1/brush.c b/dlls/d2d1/brush.c
index d8b769b..c800ba8 100644
--- a/dlls/d2d1/brush.c
+++ b/dlls/d2d1/brush.c
@@ -227,13 +227,13 @@ static void STDMETHODCALLTYPE d2d_solid_color_brush_SetColor(ID2D1SolidColorBrus
     FIXME("iface %p, color %p stub!\n", iface, color);
 }
 
-static D2D1_COLOR_F STDMETHODCALLTYPE d2d_solid_color_brush_GetColor(ID2D1SolidColorBrush *iface)
+static void STDMETHODCALLTYPE d2d_solid_color_brush_GetColor(ID2D1SolidColorBrush *iface, D2D1_COLOR_F *color)
 {
     static const D2D1_COLOR_F black = {0.0f, 0.0f, 0.0f, 1.0f};
 
     FIXME("iface %p stub!\n", iface);
 
-    return black;
+    *color = black;
 }
 
 static const struct ID2D1SolidColorBrushVtbl d2d_solid_color_brush_vtbl =
@@ -360,22 +360,22 @@ static void STDMETHODCALLTYPE d2d_linear_gradient_brush_SetEndPoint(ID2D1LinearG
     FIXME("iface %p, end_point {%.8e, %.8e} stub!\n", iface, end_point.x, end_point.y);
 }
 
-static D2D1_POINT_2F STDMETHODCALLTYPE d2d_linear_gradient_brush_GetStartPoint(ID2D1LinearGradientBrush *iface)
+static void STDMETHODCALLTYPE d2d_linear_gradient_brush_GetStartPoint(ID2D1LinearGradientBrush *iface,
+        D2D1_POINT_2F *point)
 {
-    static const D2D1_POINT_2F point = {0.0f, 0.0f};
-
     FIXME("iface %p stub!\n", iface);
 
-    return point;
+    point->x = 0.0f;
+    point->y = 0.0f;
 }
 
-static D2D1_POINT_2F STDMETHODCALLTYPE d2d_linear_gradient_brush_GetEndPoint(ID2D1LinearGradientBrush *iface)
+static void STDMETHODCALLTYPE d2d_linear_gradient_brush_GetEndPoint(ID2D1LinearGradientBrush *iface,
+        D2D1_POINT_2F *point)
 {
-    static const D2D1_POINT_2F point = {0.0f, 0.0f};
-
     FIXME("iface %p stub!\n", iface);
 
-    return point;
+    point->x = 0.0f;
+    point->y = 0.0f;
 }
 
 static void STDMETHODCALLTYPE d2d_linear_gradient_brush_GetGradientStopCollection(ID2D1LinearGradientBrush *iface,
diff --git a/dlls/d2d1/render_target.c b/dlls/d2d1/render_target.c
index 864cd31..cd87846 100644
--- a/dlls/d2d1/render_target.c
+++ b/dlls/d2d1/render_target.c
@@ -450,13 +450,13 @@ static HRESULT STDMETHODCALLTYPE d2d_d3d_render_target_EndDraw(ID2D1RenderTarget
     return S_OK;
 }
 
-static D2D1_PIXEL_FORMAT STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface)
+static void STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelFormat(ID2D1RenderTarget *iface,
+        D2D1_PIXEL_FORMAT *format)
 {
-    static const D2D1_PIXEL_FORMAT format = {DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_UNKNOWN};
-
     FIXME("iface %p stub!\n", iface);
 
-    return format;
+    format->format = DXGI_FORMAT_UNKNOWN;
+    format->alphaMode = D2D1_ALPHA_MODE_UNKNOWN;
 }
 
 static void STDMETHODCALLTYPE d2d_d3d_render_target_SetDpi(ID2D1RenderTarget *iface, float dpi_x, float dpi_y)
@@ -485,22 +485,21 @@ static void STDMETHODCALLTYPE d2d_d3d_render_target_GetDpi(ID2D1RenderTarget *if
     *dpi_y = render_target->dpi_y;
 }
 
-static D2D1_SIZE_F STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface)
+static void STDMETHODCALLTYPE d2d_d3d_render_target_GetSize(ID2D1RenderTarget *iface, D2D1_SIZE_F *size)
 {
-    static const D2D1_SIZE_F size = {0.0f, 0.0f};
-
     FIXME("iface %p stub!\n", iface);
 
-    return size;
+    size->width = 0.0f;
+    size->height = 0.0f;
 }
 
-static D2D1_SIZE_U STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface)
+static void STDMETHODCALLTYPE d2d_d3d_render_target_GetPixelSize(ID2D1RenderTarget *iface, D2D1_SIZE_U *pixel_size)
 {
     struct d2d_d3d_render_target *render_target = impl_from_ID2D1RenderTarget(iface);
 
     TRACE("iface %p.\n", iface);
 
-    return render_target->pixel_size;
+    *pixel_size = render_target->pixel_size;
 }
 
 static UINT32 STDMETHODCALLTYPE d2d_d3d_render_target_GetMaximumBitmapSize(ID2D1RenderTarget *iface)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 4f2222a..3b4338a 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -828,6 +828,13 @@ static int is_inherited_method(const type_t *iface, const var_t *func)
   return 0;
 }
 
+static int is_aggregate_return(const var_t *func)
+{
+  enum type_type type = type_get_type(type_function_get_rettype(func->type));
+  return type == TYPE_STRUCT || type == TYPE_UNION ||
+         type == TYPE_COCLASS || type == TYPE_INTERFACE;
+}
+
 static void write_method_macro(FILE *header, const type_t *iface, const char *name)
 {
   const statement_t *stmt;
@@ -846,7 +853,8 @@ static void write_method_macro(FILE *header, const type_t *iface, const char *na
       first_iface = 0;
     }
 
-    if (!is_callas(func->attrs) && !is_inherited_method(iface, func)) {
+    if (!is_callas(func->attrs) && !is_inherited_method(iface, func) &&
+        !is_aggregate_return(func)) {
       const var_t *arg;
 
       fprintf(header, "#define %s_%s(This", name, get_name(func));
@@ -947,12 +955,30 @@ static void write_inline_wrappers(FILE *header, const type_t *iface, const char
       fprintf(header, " %s_%s(", name, get_name(func));
       write_args(header, type_get_function_args(func->type), name, 1, FALSE);
       fprintf(header, ") {\n");
-      fprintf(header, "    %s", is_void(type_function_get_rettype(func->type)) ? "" : "return ");
-      fprintf(header, "This->lpVtbl->%s(This", get_name(func));
-      if (type_get_function_args(func->type))
-          LIST_FOR_EACH_ENTRY( arg, type_get_function_args(func->type), const var_t, entry )
-              fprintf(header, ",%s", arg->name);
-      fprintf(header, ");\n");
+      ++indentation;
+      if (!is_aggregate_return(func)) {
+        indent(header, 0);
+        fprintf(header, "%sThis->lpVtbl->%s(This",
+                is_void(type_function_get_rettype(func->type)) ? "" : "return ",
+                get_name(func));
+        if (type_get_function_args(func->type))
+          LIST_FOR_EACH_ENTRY(arg, type_get_function_args(func->type), const var_t, entry)
+            fprintf(header, ",%s", arg->name);
+        fprintf(header, ");\n");
+      } else {
+        indent(header, 0);
+        write_type_decl_left(header, type_function_get_rettype(func->type));
+        fprintf(header, " __ret;\n");
+        indent(header, 0);
+        fprintf(header, "This->lpVtbl->%s(This,&__ret", get_name(func));
+        if (type_get_function_args(func->type))
+          LIST_FOR_EACH_ENTRY(arg, type_get_function_args(func->type), const var_t, entry)
+            fprintf(header, ",%s", arg->name);
+        fprintf(header, ");\n");
+        indent(header, 0);
+        fprintf(header, "return __ret;\n");
+      }
+      --indentation;
       fprintf(header, "}\n");
     }
   }
@@ -978,12 +1004,28 @@ static void do_write_c_method_def(FILE *header, const type_t *iface, const char
       const char *callconv = get_attrp(func->type->attrs, ATTR_CALLCONV);
       if (!callconv) callconv = "STDMETHODCALLTYPE";
       indent(header, 0);
-      write_type_decl_left(header, type_function_get_rettype(func->type));
+      if (!is_aggregate_return(func))
+        write_type_decl_left(header, type_function_get_rettype(func->type));
+      else
+        fprintf(header, "void");
       if (is_inherited_method(iface, func))
         fprintf(header, " (%s *%s_%s)(\n", callconv, iface->name, func->name);
       else
         fprintf(header, " (%s *%s)(\n", callconv, get_name(func));
-      write_args(header, type_get_function_args(func->type), name, 1, TRUE);
+      ++indentation;
+      indent(header, 0);
+      fprintf(header, "%s *This", name);
+      if (is_aggregate_return(func)) {
+        fprintf(header, ",\n");
+        indent(header, 0);
+        write_type_decl_left(header, type_function_get_rettype(func->type));
+        fprintf(header, " *__ret");
+      }
+      --indentation;
+      if (type_get_function_args(func->type)) {
+        fprintf(header, ",\n");
+        write_args(header, type_get_function_args(func->type), name, 0, TRUE);
+      }
       fprintf(header, ");\n");
       fprintf(header, "\n");
     }
-- 
1.7.10.4




More information about the wine-patches mailing list